diff options
author | Stephen Toub <stoub@microsoft.com> | 2019-05-28 06:04:13 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-28 06:04:13 -0400 |
commit | 4a1275434fff99206f2a28f5f0e87f124069eb7f (patch) | |
tree | 4e5c7667e29c969179a965048f2452f4d4bad3ad /src/System.Private.CoreLib/shared/System/Threading/Tasks | |
parent | bb75edbac9c40034b6683c17d86057ee9bf4192d (diff) | |
download | coreclr-4a1275434fff99206f2a28f5f0e87f124069eb7f.tar.gz coreclr-4a1275434fff99206f2a28f5f0e87f124069eb7f.tar.bz2 coreclr-4a1275434fff99206f2a28f5f0e87f124069eb7f.zip |
Add and apply nullable attributes (#24679)
* Add and apply nullable attributes
* Adapt to API review decisions
* Address PR feedback
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Threading/Tasks')
12 files changed, 163 insertions, 149 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs index 9065ae1666..50014bf597 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs @@ -152,7 +152,11 @@ namespace System.Threading.Tasks private CompletionState EnsureCompletionStateInitialized() { // ValueLock not needed, but it's ok if it's held - return LazyInitializer.EnsureInitialized<CompletionState>(ref m_completionState!, () => new CompletionState()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 +#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected +#pragma warning disable CS8603 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected + return LazyInitializer.EnsureInitialized(ref m_completionState!, () => new CompletionState()); +#pragma warning restore CS8603 +#pragma warning restore CS8634 } /// <summary>Gets whether completion has been requested.</summary> @@ -297,7 +301,7 @@ namespace System.Threading.Tasks { try { - processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessExclusiveTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessExclusiveTasks(), this, default, GetCreationOptionsForTask(fairly)); processingTask.Start(m_underlyingTaskScheduler); // When we call Start, if the underlying scheduler throws in QueueTask, TPL will fault the task and rethrow @@ -327,7 +331,7 @@ namespace System.Threading.Tasks { try { - processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessConcurrentTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessConcurrentTasks(), this, default, GetCreationOptionsForTask(fairly)); processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs index c82372c000..1a7899d97c 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; @@ -60,7 +61,8 @@ namespace System.Threading.Tasks [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")] public class Task<TResult> : Task { - internal TResult m_result = default!; // The value itself, if set. // TODO-NULLABLE-GENERIC + // The value itself, if set. + [MaybeNull] internal TResult m_result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected private static readonly TaskFactory<TResult> s_Factory = new TaskFactory<TResult>(); @@ -95,7 +97,7 @@ namespace System.Threading.Tasks m_result = result; } - internal Task(bool canceled, TResult result, TaskCreationOptions creationOptions, CancellationToken ct) + internal Task(bool canceled, [AllowNull] TResult result, TaskCreationOptions creationOptions, CancellationToken ct) : base(canceled, creationOptions, ct) { if (!canceled) @@ -209,7 +211,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ArgumentException"> /// The <paramref name="function"/> argument is null. /// </exception> - public Task(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Func<object?, TResult> function, object? state) : this(function, state, null, default, TaskCreationOptions.None, InternalTaskOptions.None, null) { @@ -230,7 +232,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> /// has already been disposed. /// </exception> - public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) : this(function, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null) { @@ -255,7 +257,7 @@ namespace System.Threading.Tasks /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>. /// </exception> - public Task(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) : this(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) { @@ -285,7 +287,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> /// has already been disposed. /// </exception> - public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) : this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) { @@ -337,7 +339,7 @@ namespace System.Threading.Tasks } // Create and schedule the future. - Task<TResult> f = new Task<TResult>(function!, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + Task<TResult> f = new Task<TResult>(function!, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected f.ScheduleAndStart(false); return f; @@ -357,7 +359,7 @@ namespace System.Threading.Tasks } // Create and schedule the future. - Task<TResult> f = new Task<TResult>(function!, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + Task<TResult> f = new Task<TResult>(function!, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected f.ScheduleAndStart(false); return f; @@ -383,7 +385,7 @@ namespace System.Threading.Tasks // internal helper function breaks out logic used by TaskCompletionSource - internal bool TrySetResult(TResult result) + internal bool TrySetResult([AllowNull] TResult result) { Debug.Assert(m_action == null, "Task<T>.TrySetResult(): non-null m_action"); @@ -725,13 +727,13 @@ namespace System.Threading.Tasks out internalOptions); Task continuationTask = new ContinuationTaskFromResultTask<TResult>( - this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationAction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationTask; } @@ -756,7 +758,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ArgumentNullException"> /// The <paramref name="continuationAction"/> argument is null. /// </exception> - public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state) { return ContinueWith(continuationAction, state, TaskScheduler.Current, default, TaskContinuationOptions.None); } @@ -783,7 +785,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> /// has already been disposed. /// </exception> - public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken) { return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); } @@ -812,7 +814,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ArgumentNullException"> /// The <paramref name="scheduler"/> argument is null. /// </exception> - public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler) { return ContinueWith(continuationAction, state, scheduler, default, TaskContinuationOptions.None); } @@ -846,7 +848,7 @@ namespace System.Threading.Tasks /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>. /// </exception> - public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions) { return ContinueWith(continuationAction, state, TaskScheduler.Current, default, continuationOptions); } @@ -890,14 +892,14 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> /// has already been disposed. /// </exception> - public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions); } // Same as the above overload, only with a stack mark. - internal Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + internal Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions) { if (continuationAction == null) @@ -918,13 +920,13 @@ namespace System.Threading.Tasks out internalOptions); Task continuationTask = new ContinuationTaskFromResultTask<TResult>( - this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationAction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationTask; } @@ -1134,13 +1136,13 @@ namespace System.Threading.Tasks out internalOptions); Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>( - this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationFunction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationFuture; } @@ -1357,13 +1359,13 @@ namespace System.Threading.Tasks out internalOptions); Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>( - this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationFunction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationFuture; } @@ -1384,7 +1386,7 @@ namespace System.Threading.Tasks m_task = task; } - public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default!; } } // TODO-NULLABLE-GENERIC + [MaybeNull] public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default!; } } public object? AsyncState { get { return m_task.AsyncState; } } public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } } public Exception? Exception { get { return m_task.Exception; } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs index e8be5bd091..139e32fda3 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Threading.Tasks { @@ -376,7 +377,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew(Func<object?, TResult> function, object? state) { Task? currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken, @@ -405,7 +406,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) { Task? currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, state, cancellationToken, @@ -436,7 +437,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) { Task? currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken, @@ -478,7 +479,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) { return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken, creationOptions, InternalTaskOptions.None, scheduler); @@ -500,7 +501,7 @@ namespace System.Threading.Tasks Exception? ex = null; OperationCanceledException? oce = null; - TResult result = default!; // TODO-NULLABLE-GENERIC + TResult result = default!; try { @@ -671,9 +672,9 @@ namespace System.Threading.Tasks if (Task.s_asyncDebuggingEnabled) Task.AddToActiveTasks(t); - if (asyncResult!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + if (asyncResult!.IsCompleted) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { - try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions } else @@ -682,7 +683,7 @@ namespace System.Threading.Tasks asyncResult.AsyncWaitHandle, delegate { - try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions }, null, @@ -712,7 +713,7 @@ namespace System.Threading.Tasks /// </remarks> public Task<TResult> FromAsync( Func<AsyncCallback, object?, IAsyncResult> beginMethod, - Func<IAsyncResult, TResult> endMethod, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + Func<IAsyncResult, TResult> endMethod, object? state) { return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions); } @@ -741,7 +742,7 @@ namespace System.Threading.Tasks /// </remarks> public Task<TResult> FromAsync( Func<AsyncCallback, object?, IAsyncResult> beginMethod, - Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions) { return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions); } @@ -765,7 +766,7 @@ namespace System.Threading.Tasks Task<TResult> promise = new Task<TResult>(state, creationOptions); if (AsyncCausalityTracer.LoggingOn) - AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (Task.s_asyncDebuggingEnabled) Task.AddToActiveTasks(promise); @@ -773,7 +774,7 @@ namespace System.Threading.Tasks try { //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod!(iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + var asyncResult = beginMethod!(iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); @@ -824,7 +825,7 @@ namespace System.Threading.Tasks public Task<TResult> FromAsync<TArg1>( Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod, - TArg1 arg1, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + TArg1 arg1, object? state) { return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions); } @@ -858,7 +859,7 @@ namespace System.Threading.Tasks public Task<TResult> FromAsync<TArg1>( Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod, - TArg1 arg1, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + TArg1 arg1, object? state, TaskCreationOptions creationOptions) { return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions); } @@ -882,7 +883,7 @@ namespace System.Threading.Tasks Task<TResult> promise = new Task<TResult>(state, creationOptions); if (AsyncCausalityTracer.LoggingOn) - AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (Task.s_asyncDebuggingEnabled) Task.AddToActiveTasks(promise); @@ -890,7 +891,7 @@ namespace System.Threading.Tasks try { //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod!(arg1, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + var asyncResult = beginMethod!(arg1, iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); @@ -945,7 +946,7 @@ namespace System.Threading.Tasks public Task<TResult> FromAsync<TArg1, TArg2>( Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod, - TArg1 arg1, TArg2 arg2, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + TArg1 arg1, TArg2 arg2, object? state) { return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions); } @@ -983,7 +984,7 @@ namespace System.Threading.Tasks public Task<TResult> FromAsync<TArg1, TArg2>( Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod, - TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) { return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions); } @@ -992,7 +993,7 @@ namespace System.Threading.Tasks // method can access the logic w/o declaring a TaskFactory<TResult> instance. internal static Task<TResult> FromAsyncImpl<TArg1, TArg2>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod, Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction, - TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) { if (beginMethod == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod); @@ -1007,7 +1008,7 @@ namespace System.Threading.Tasks Task<TResult> promise = new Task<TResult>(state, creationOptions); if (AsyncCausalityTracer.LoggingOn) - AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (Task.s_asyncDebuggingEnabled) Task.AddToActiveTasks(promise); @@ -1015,7 +1016,7 @@ namespace System.Threading.Tasks try { //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod!(arg1, arg2, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + var asyncResult = beginMethod!(arg1, arg2, iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); @@ -1140,7 +1141,7 @@ namespace System.Threading.Tasks Task<TResult> promise = new Task<TResult>(state, creationOptions); if (AsyncCausalityTracer.LoggingOn) - AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (Task.s_asyncDebuggingEnabled) Task.AddToActiveTasks(promise); @@ -1148,7 +1149,7 @@ namespace System.Threading.Tasks try { //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod!(arg1, arg2, arg3, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + var asyncResult = beginMethod!(arg1, arg2, arg3, iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); @@ -1228,7 +1229,7 @@ namespace System.Threading.Tasks internal static readonly AsyncCallback s_completeFromAsyncResult = CompleteFromAsyncResult; /// <summary>A reference to the object on which the begin/end methods are invoked.</summary> - private TInstance m_thisRef; + [AllowNull, MaybeNull] private TInstance m_thisRef; /// <summary>The end method.</summary> private Func<TInstance, IAsyncResult, TResult>? m_endMethod; @@ -1253,13 +1254,13 @@ namespace System.Threading.Tasks // Validate argument if (asyncResult == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult); - var promise = asyncResult!.AsyncState as FromAsyncTrimPromise<TInstance>; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + var promise = asyncResult!.AsyncState as FromAsyncTrimPromise<TInstance>; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (promise == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult); // Grab the relevant state and then null it out so that the task doesn't hold onto the state unnecessarily - var thisRef = promise!.m_thisRef; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + var thisRef = promise!.m_thisRef; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected var endMethod = promise.m_endMethod; - promise.m_thisRef = default!; // TODO-NULLABLE-GENERIC + promise.m_thisRef = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected promise.m_endMethod = null; if (endMethod == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult); @@ -1267,7 +1268,7 @@ namespace System.Threading.Tasks // we'll instead complete the promise at the call site. if (!asyncResult.CompletedSynchronously) { - promise.Complete(thisRef, endMethod!, asyncResult, requiresSynchronization: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + promise.Complete(thisRef, endMethod!, asyncResult, requiresSynchronization: true); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } } @@ -1322,7 +1323,7 @@ namespace System.Threading.Tasks { TaskCreationOptions tco; Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out _); - return new Task<TResult>(true, default!, tco, ct); // TODO-NULLABLE-GENERIC + return new Task<TResult>(true, default!, tco, ct); // TODO-NULLABLE: Remove ! when nullable attributes are respected } // @@ -1610,7 +1611,7 @@ namespace System.Threading.Tasks if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler); // Check tasks array and make defensive copy - Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected // Bail early if cancellation has been requested. if (cancellationToken.IsCancellationRequested @@ -1629,7 +1630,7 @@ namespace System.Threading.Tasks return starter.ContinueWith<TResult>( // use a cached delegate GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate, - continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } else { @@ -1638,7 +1639,7 @@ namespace System.Threading.Tasks return starter.ContinueWith<TResult>( // use a cached delegate GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate, - continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } } @@ -1656,7 +1657,7 @@ namespace System.Threading.Tasks if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler); // Check tasks array and make defensive copy - Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected // Bail early if cancellation has been requested. if (cancellationToken.IsCancellationRequested @@ -1682,7 +1683,7 @@ namespace System.Threading.Tasks Debug.Assert(state is Func<Task[], TResult>); return ((Func<Task[], TResult>)state)(completedTasks.Result); }, - continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } else { @@ -1695,9 +1696,9 @@ namespace System.Threading.Tasks { completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary(); Debug.Assert(state is Action<Task[]>); - ((Action<Task[]>)state)(completedTasks.Result); return default!; // TODO-NULLABLE-GENERIC + ((Action<Task[]>)state)(completedTasks.Result); return default!; }, - continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } } @@ -1980,7 +1981,7 @@ namespace System.Threading.Tasks // check arguments TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions); if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); - if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected //ArgumentNullException of continuationFunction or continuationAction is checked by the caller Debug.Assert((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null"); @@ -2008,7 +2009,7 @@ namespace System.Threading.Tasks Debug.Assert(state is Func<Task, TResult>); return ((Func<Task, TResult>)state)(completedTask.Result); }, - continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } else { @@ -2020,9 +2021,9 @@ namespace System.Threading.Tasks { Debug.Assert(state is Action<Task>); ((Action<Task>)state)(completedTask.Result); - return default!; // TODO-NULLABLE-GENERIC + return default!; }, - continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } } @@ -2036,7 +2037,7 @@ namespace System.Threading.Tasks // check arguments TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions); if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); - if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected //ArgumentNullException of continuationFunction or continuationAction is checked by the caller Debug.Assert((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null"); if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler); @@ -2058,7 +2059,7 @@ namespace System.Threading.Tasks return starter.ContinueWith<TResult>( // Use a cached delegate GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate, - continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } else { @@ -2066,7 +2067,7 @@ namespace System.Threading.Tasks return starter.ContinueWith<TResult>( // Use a cached delegate GenericDelegateCache<TAntecedentResult, TResult>.CWAnyActionDelegate, - continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } } } @@ -2094,7 +2095,7 @@ namespace System.Threading.Tasks var action = (Action<Task<TAntecedentResult>>)state; var arg = (Task<TAntecedentResult>)wrappedWinner.Result; action(arg); - return default!; // TODO-NULLABLE-GENERIC + return default!; }; // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationFunction) @@ -2115,7 +2116,7 @@ namespace System.Threading.Tasks Debug.Assert(state is Action<Task<TAntecedentResult>[]>); var action = (Action<Task<TAntecedentResult>[]>)state; action(wrappedAntecedents.Result); - return default!; // TODO-NULLABLE-GENERIC + return default!; }; } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs index 157ad5d666..9fa82edb6e 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs @@ -25,6 +25,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace System.Threading.Tasks @@ -42,7 +43,7 @@ namespace System.Threading.Tasks /// <param name="result">The dequeued item.</param> /// <returns>true if an item could be dequeued; otherwise, false.</returns> /// <remarks>This method is meant to be thread-safe subject to the particular nature of the implementation.</remarks> - bool TryDequeue(out T result); + bool TryDequeue([MaybeNullWhen(false)] out T result); /// <summary>Gets whether the collection is currently empty.</summary> /// <remarks>This method may or may not be thread-safe.</remarks> @@ -67,7 +68,7 @@ namespace System.Threading.Tasks /// <summary>Attempts to dequeue an item from the queue.</summary> /// <param name="result">The dequeued item.</param> /// <returns>true if an item could be dequeued; otherwise, false.</returns> - bool IProducerConsumerQueue<T>.TryDequeue(out T result) { return base.TryDequeue(out result); } + bool IProducerConsumerQueue<T>.TryDequeue([MaybeNullWhen(false)] out T result) { return base.TryDequeue(out result); } /// <summary>Gets whether the collection is currently empty.</summary> bool IProducerConsumerQueue<T>.IsEmpty { get { return base.IsEmpty; } } @@ -194,7 +195,7 @@ namespace System.Threading.Tasks /// <summary>Attempts to dequeue an item from the queue.</summary> /// <param name="result">The dequeued item.</param> /// <returns>true if an item could be dequeued; otherwise, false.</returns> - public bool TryDequeue(out T result) + public bool TryDequeue([MaybeNullWhen(false)] out T result) { Segment segment = m_head; var array = segment.m_array; @@ -204,7 +205,7 @@ namespace System.Threading.Tasks if (first != segment.m_state.m_lastCopy) { result = array[first]; - array[first] = default!; // Clear the slot to release the element // TODO-NULLABLE-GENERIC + array[first] = default!; // Clear the slot to release the element segment.m_state.m_first = (first + 1) & (array.Length - 1); return true; } @@ -217,7 +218,7 @@ namespace System.Threading.Tasks /// <param name="segment">The segment from which the item was dequeued.</param> /// <param name="result">The dequeued item.</param> /// <returns>true if an item could be dequeued; otherwise, false.</returns> - private bool TryDequeueSlow(ref Segment segment, ref T[] array, out T result) + private bool TryDequeueSlow(ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result) { Debug.Assert(segment != null, "Expected a non-null segment."); Debug.Assert(array != null, "Expected a non-null item array."); @@ -239,12 +240,12 @@ namespace System.Threading.Tasks if (first == segment.m_state.m_last) { - result = default!; // TODO-NULLABLE-GENERIC + result = default!; return false; } result = array[first]; - array[first] = default!; // Clear the slot to release the element // TODO-NULLABLE-GENERIC + array[first] = default!; // Clear the slot to release the element segment.m_state.m_first = (first + 1) & (segment.m_array.Length - 1); segment.m_state.m_lastCopy = segment.m_state.m_last; // Refresh m_lastCopy to ensure that m_first has not passed m_lastCopy diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs index 8f460370c0..5f071b2749 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs @@ -53,7 +53,7 @@ namespace System.Threading.Tasks.Sources /// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param> /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param> /// <param name="flags">The flags describing the behavior of the continuation.</param> - void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); /// <summary>Gets the result of the <see cref="IValueTaskSource"/>.</summary> /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param> @@ -73,7 +73,7 @@ namespace System.Threading.Tasks.Sources /// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param> /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param> /// <param name="flags">The flags describing the behavior of the continuation.</param> - void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); /// <summary>Gets the result of the <see cref="IValueTaskSource{TResult}"/>.</summary> /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param> diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs index fd68a4985a..e72328ac54 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; @@ -31,7 +32,7 @@ namespace System.Threading.Tasks.Sources /// <summary>Whether the current operation has completed.</summary> private bool _completed; /// <summary>The result with which the operation succeeded, or the default value if it hasn't yet completed or failed.</summary> - private TResult _result; + [AllowNull, MaybeNull] private TResult _result; /// <summary>The exception with which the operation failed, or null if it hasn't yet completed or completed successfully.</summary> private ExceptionDispatchInfo? _error; /// <summary>The current version of this value, used to help prevent misuse.</summary> @@ -47,7 +48,7 @@ namespace System.Threading.Tasks.Sources // Reset/update state for the next use/await of this instance. _version++; _completed = false; - _result = default!; // TODO-NULLABLE-GENERIC + _result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected _error = null; _executionContext = null; _capturedContext = null; @@ -106,7 +107,7 @@ namespace System.Threading.Tasks.Sources /// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param> /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param> /// <param name="flags">The flags describing the behavior of the continuation.</param> - public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) { if (continuation == null) { @@ -175,7 +176,7 @@ namespace System.Threading.Tasks.Sources case SynchronizationContext sc: sc.Post(s => { - var tuple = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + var tuple = (Tuple<Action<object?>, object?>)s!; tuple.Item1(tuple.Item2); }, Tuple.Create(continuation, state)); break; @@ -254,7 +255,7 @@ namespace System.Threading.Tasks.Sources case SynchronizationContext sc: sc.Post(s => { - var state = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + var state = (Tuple<Action<object?>, object?>)s!; state.Item1(state.Item2); }, Tuple.Create(_continuation, _continuationState)); break; diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs index a4a65922cc..4fb8d9aff9 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @@ -207,12 +207,14 @@ namespace System.Threading.Tasks { Debug.Assert(task != null, "Null Task objects can't be added to the ActiveTasks collection"); +#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected LazyInitializer.EnsureInitialized(ref s_currentActiveTasks, () => new Dictionary<int, Task>()); +#pragma warning restore CS8634 int taskId = task.Id; - lock (s_currentActiveTasks!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + lock (s_currentActiveTasks!) // TODO-NULLABLE: Remove ! when nullable attributes are respected { - s_currentActiveTasks![taskId] = task; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + s_currentActiveTasks[taskId] = task; } //always return true to keep signature as bool for backwards compatibility return true; @@ -427,7 +429,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ArgumentNullException"> /// The <paramref name="action"/> argument is null. /// </exception> - public Task(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Action<object?> action, object? state) : this(action, state, null, default, TaskCreationOptions.None, InternalTaskOptions.None, null) { } @@ -444,7 +446,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> /// has already been disposed. /// </exception> - public Task(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Action<object?> action, object? state, CancellationToken cancellationToken) : this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null) { } @@ -465,7 +467,7 @@ namespace System.Threading.Tasks /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>. /// </exception> - public Task(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Action<object?> action, object? state, TaskCreationOptions creationOptions) : this(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) { } @@ -490,7 +492,7 @@ namespace System.Threading.Tasks /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> /// has already been disposed. /// </exception> - public Task(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) : this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) { } @@ -634,7 +636,7 @@ namespace System.Threading.Tasks if (antecedent == null) { // if no antecedent was specified, use this task's reference as the cancellation state object - ctr = cancellationToken.UnsafeRegister(t => ((Task)t!).InternalCancel(false), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + ctr = cancellationToken.UnsafeRegister(t => ((Task)t!).InternalCancel(false), this); } else { @@ -1050,7 +1052,7 @@ namespace System.Threading.Tasks ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler); } - InternalRunSynchronously(scheduler!, waitForCompletion: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + InternalRunSynchronously(scheduler!, waitForCompletion: true); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } // @@ -1356,7 +1358,9 @@ namespace System.Threading.Tasks /// <returns>The initialized contingent properties object.</returns> internal ContingentProperties EnsureContingentPropertiesInitialized() { - return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties())!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 +#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected + return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties())!; +#pragma warning restore CS8634 } /// <summary> @@ -1525,7 +1529,7 @@ namespace System.Threading.Tasks } } - return contingentProps.m_completionEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + return contingentProps.m_completionEvent!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability } } @@ -1815,7 +1819,7 @@ namespace System.Threading.Tasks lock (props) { - props.m_exceptionsHolder!.Add(exceptionObject, representsCancellation); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + props.m_exceptionsHolder!.Add(exceptionObject, representsCancellation); // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability } } @@ -3613,13 +3617,13 @@ namespace System.Threading.Tasks CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions); Task continuationTask = new ContinuationTaskFromTask( - this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationAction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationTask; } @@ -3803,13 +3807,13 @@ namespace System.Threading.Tasks CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions); Task continuationTask = new ContinuationTaskFromTask( - this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationAction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationTask; } @@ -4006,13 +4010,13 @@ namespace System.Threading.Tasks CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions); Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>( - this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationFunction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationTask; } @@ -4213,13 +4217,13 @@ namespace System.Threading.Tasks CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions); Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>( - this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + this, continuationFunction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected creationOptions, internalOptions ); // Register the continuation. If synchronous execution is requested, this may // actually invoke the continuation before returning. - ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected return continuationTask; } @@ -4724,7 +4728,7 @@ namespace System.Threading.Tasks bool returnValue = true; // Collects incomplete tasks in "waitedOnTaskList" - for (int i = tasks!.Length - 1; i >= 0; i--) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + for (int i = tasks!.Length - 1; i >= 0; i--) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { Task task = tasks[i]; @@ -4733,7 +4737,7 @@ namespace System.Threading.Tasks ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks); } - bool taskIsCompleted = task!.IsCompleted; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + bool taskIsCompleted = task!.IsCompleted; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (!taskIsCompleted) { // try inlining the task only if we have an infinite timeout and an empty cancellation token @@ -5089,7 +5093,7 @@ namespace System.Threading.Tasks // Make a pass through the loop to check for any tasks that may have // already been completed, and to verify that no tasks are null. - for (int taskIndex = 0; taskIndex < tasks!.Length; taskIndex++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + for (int taskIndex = 0; taskIndex < tasks!.Length; taskIndex++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { Task task = tasks[taskIndex]; @@ -5098,7 +5102,7 @@ namespace System.Threading.Tasks ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks); } - if (signaledTaskIndex == -1 && task!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + if (signaledTaskIndex == -1 && task!.IsCompleted) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { // We found our first completed task. Store it, but we can't just return here, // as we still need to validate the whole array for nulls. @@ -5150,7 +5154,7 @@ namespace System.Threading.Tasks if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception); var task = new Task(); - bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected Debug.Assert(succeeded, "This should always succeed on a new task."); return task; } @@ -5164,7 +5168,7 @@ namespace System.Threading.Tasks if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception); var task = new Task<TResult>(); - bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected Debug.Assert(succeeded, "This should always succeed on a new task."); return task; } @@ -5187,7 +5191,7 @@ namespace System.Threading.Tasks { if (!cancellationToken.IsCancellationRequested) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.cancellationToken); - return new Task<TResult>(true, default!, TaskCreationOptions.None, cancellationToken); // TODO-NULLABLE-GENERIC + return new Task<TResult>(true, default!, TaskCreationOptions.None, cancellationToken); // TODO-NULLABLE: Remove ! when nullable attributes are respected } /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified exception.</summary> @@ -5324,7 +5328,7 @@ namespace System.Threading.Tasks return Task.FromCanceled(cancellationToken); // Kick off initial Task, which will call the user-supplied function and yield a Task. - Task<Task?> task1 = Task<Task?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + Task<Task?> task1 = Task<Task?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected // Create a promise-style Task to be used as a proxy for the operation // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation. @@ -5369,7 +5373,7 @@ namespace System.Threading.Tasks return Task.FromCanceled<TResult>(cancellationToken); // Kick off initial Task, which will call the user-supplied function and yield a Task. - Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected // Create a promise-style Task to be used as a proxy for the operation // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation. @@ -5492,7 +5496,7 @@ namespace System.Threading.Tasks if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout { - _timer = new TimerQueueTimer(state => ((DelayPromise)state!).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + _timer = new TimerQueueTimer(state => ((DelayPromise)state!).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); if (IsCanceled) { // Handle rare race condition where cancellation occurs prior to our having created and stored the timer, in which case @@ -5531,7 +5535,7 @@ namespace System.Threading.Tasks Debug.Assert(token.CanBeCanceled); _token = token; - _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state!).CompleteCanceled(), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state!).CompleteCanceled(), this); } private void CompleteCanceled() @@ -5596,7 +5600,7 @@ namespace System.Threading.Tasks foreach (var task in tasks) { if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + taskArray[index++] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } return InternalWhenAll(taskArray); } @@ -5604,10 +5608,10 @@ namespace System.Threading.Tasks // Do some argument checking and convert tasks to a List (and later an array). if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); List<Task> taskList = new List<Task>(); - foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + foreach (Task task in tasks!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + taskList.Add(task!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } // Delegate the rest to InternalWhenAll() @@ -5646,7 +5650,7 @@ namespace System.Threading.Tasks // Do some argument checking and make a defensive copy of the tasks array if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); - int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + int taskCount = tasks!.Length; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (taskCount == 0) return InternalWhenAll(tasks); // Small optimization in the case of an empty array. Task[] tasksCopy = new Task[taskCount]; @@ -5654,7 +5658,7 @@ namespace System.Threading.Tasks { Task task = tasks[i]; if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + tasksCopy[i] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } // The rest can be delegated to InternalWhenAll() @@ -5840,7 +5844,7 @@ namespace System.Threading.Tasks foreach (var task in tasks) { if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + taskArray[index++] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } return InternalWhenAll<TResult>(taskArray); } @@ -5848,10 +5852,10 @@ namespace System.Threading.Tasks // Do some argument checking and convert tasks into a List (later an array) if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); List<Task<TResult>> taskList = new List<Task<TResult>>(); - foreach (Task<TResult> task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + foreach (Task<TResult> task in tasks!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + taskList.Add(task!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } // Delegate the rest to InternalWhenAll<TResult>(). @@ -5893,7 +5897,7 @@ namespace System.Threading.Tasks // Do some argument checking and make a defensive copy of the tasks array if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); - int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + int taskCount = tasks!.Length; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (taskCount == 0) return InternalWhenAll<TResult>(tasks); // small optimization in the case of an empty task array Task<TResult>[] tasksCopy = new Task<TResult>[taskCount]; @@ -5901,7 +5905,7 @@ namespace System.Threading.Tasks { Task<TResult> task = tasks[i]; if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + tasksCopy[i] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } // Delegate the rest to InternalWhenAll<TResult>() @@ -6060,7 +6064,7 @@ namespace System.Threading.Tasks public static Task<Task> WhenAny(params Task[] tasks) { if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); - if (tasks!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + if (tasks!.Length == 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); } @@ -6073,7 +6077,7 @@ namespace System.Threading.Tasks { Task task = tasks[i]; if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + tasksCopy[i] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } // Previously implemented CommonCWAnyLogic() can handle the rest @@ -6102,10 +6106,10 @@ namespace System.Threading.Tasks // Make a defensive copy, as the user may manipulate the tasks collection // after we return but before the WhenAny asynchronously completes. List<Task> taskList = new List<Task>(); - foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + foreach (Task task in tasks!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); - taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + taskList.Add(task!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } if (taskList.Count == 0) @@ -6597,7 +6601,7 @@ namespace System.Threading.Tasks ThreadPool.UnsafeQueueUserWorkItem(state => { // InvokeCore(completingTask); - var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!; tuple.Item1.InvokeCore(tuple.Item2); }, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask)); } @@ -6673,7 +6677,7 @@ namespace System.Threading.Tasks if (Task.s_asyncDebuggingEnabled) RemoveFromActiveTasks(this); - result = TrySetResult(taskTResult != null ? taskTResult.Result : default!); // TODO-NULLABLE-GENERIC + result = TrySetResult(taskTResult != null ? taskTResult.Result : default!); // TODO-NULLABLE: Remove ! when nullable attributes are respected break; } return result; diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs index 8773eb4159..b0c79e61ba 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs @@ -150,7 +150,7 @@ namespace System.Threading.Tasks { if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception); - bool rval = _task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + bool rval = _task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected if (!rval && !_task.IsCompleted) SpinUntilCompleted(); return rval; } @@ -180,11 +180,11 @@ namespace System.Threading.Tasks if (exceptions == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exceptions); List<Exception> defensiveCopy = new List<Exception>(); - foreach (Exception e in exceptions!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + foreach (Exception e in exceptions!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { if (e == null) ThrowHelper.ThrowArgumentException(ExceptionResource.TaskCompletionSourceT_TrySetException_NullException, ExceptionArgument.exceptions); - defensiveCopy.Add(e!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + defensiveCopy.Add(e!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected } if (defensiveCopy.Count == 0) @@ -216,7 +216,7 @@ namespace System.Threading.Tasks { if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception); - if (!TrySetException(exception!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + if (!TrySetException(exception!)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted); } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs index 65547fb452..fbe77339cc 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs @@ -492,7 +492,7 @@ namespace System.Threading.Tasks { try { - ((Action)state!)(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + ((Action)state!)(); } catch (Exception exception) { diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs index 3929a08589..786e132e7b 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs @@ -396,7 +396,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task StartNew(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task StartNew(Action<object?> action, object? state) { Task? currTask = Task.InternalCurrent; return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask), @@ -425,7 +425,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken) { Task? currTask = Task.InternalCurrent; return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask), @@ -455,7 +455,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task StartNew(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task StartNew(Action<object?> action, object? state, TaskCreationOptions creationOptions) { Task? currTask = Task.InternalCurrent; return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask), @@ -496,7 +496,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) { return Task.InternalStartNew( @@ -657,7 +657,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state) { Task? currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken, @@ -690,7 +690,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) { Task? currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, state, cancellationToken, @@ -724,7 +724,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) { Task? currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken, @@ -769,7 +769,7 @@ namespace System.Threading.Tasks /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// </remarks> - public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) { return Task<TResult>.StartNew( diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs index b6afade5a5..f79a87ac06 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs @@ -298,7 +298,7 @@ namespace System.Threading.Tasks Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object?>(), null); activeTaskSchedulers = s_activeTaskSchedulers; } - activeTaskSchedulers!.Add(this, null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + activeTaskSchedulers!.Add(this, null); // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability } /// <summary> diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs index 884ae0b009..75c6fd9a32 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks.Sources; @@ -415,7 +416,7 @@ namespace System.Threading.Tasks /// <summary>null if <see cref="_result"/> has the result, otherwise a <see cref="Task{TResult}"/> or a <see cref="IValueTaskSource{TResult}"/>.</summary> internal readonly object? _obj; /// <summary>The result to be used if the operation completed successfully synchronously.</summary> - internal readonly TResult _result; + [AllowNull] internal readonly TResult _result; /// <summary>Opaque value passed through to the <see cref="IValueTaskSource{TResult}"/>.</summary> internal readonly short _token; /// <summary>true to continue on the captured context; otherwise, false.</summary> @@ -449,7 +450,7 @@ namespace System.Threading.Tasks _obj = task; - _result = default!; // TODO-NULLABLE-GENERIC + _result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected _continueOnCapturedContext = true; _token = 0; } @@ -468,7 +469,7 @@ namespace System.Threading.Tasks _obj = source; _token = token; - _result = default!; // TODO-NULLABLE-GENERIC + _result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected _continueOnCapturedContext = true; } |