Nullable: System.Threading.Tasks (#23691)
authorStephen Toub <stoub@microsoft.com>
Thu, 4 Apr 2019 01:00:16 +0000 (21:00 -0400)
committerGitHub <noreply@github.com>
Thu, 4 Apr 2019 01:00:16 +0000 (21:00 -0400)
* Nullable: System.Threading.Tasks

* Address PR feedback

33 files changed:
src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
src/System.Private.CoreLib/shared/System/IAsyncResult.cs
src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracerConstants.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExceptionHolder.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskSchedulerException.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskToApm.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/TplEventSource.cs
src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
src/System.Private.CoreLib/shared/System/Threading/Timer.cs
src/System.Private.CoreLib/src/System/Delegate.cs
src/System.Private.CoreLib/src/System/MulticastDelegate.cs
src/System.Private.CoreLib/src/System/Threading/Tasks/AsyncCausalityTracer.cs
src/System.Private.CoreLib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs

index 6a6764a..bbb07a7 100644 (file)
@@ -16,7 +16,7 @@ namespace System.Globalization
     public partial class CompareInfo
     {
         [NonSerialized]
-        private Interop.Globalization.SafeSortHandle _sortHandle = null!;
+        private Interop.Globalization.SafeSortHandle _sortHandle = null!; // initialized in helper called by ctors
 
         [NonSerialized]
         private bool _isAsciiEqualityOrdinal;
index 12f8ce2..7e1e668 100644 (file)
@@ -56,7 +56,7 @@ namespace System.Globalization
         private const int undef = -1;
 
         // Override flag
-        private string _sRealName = null!; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
+        private string _sRealName = null!; // Name you passed in (ie: en-US, en, or de-DE_phoneb). Initialized by helper called during initialization.
         private string? _sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
 
         // Identity
index 4ff0554..78c9790 100644 (file)
@@ -88,7 +88,7 @@ namespace System.Globalization
         private const string sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
         private const string universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
 
-        private Calendar calendar = null!;
+        private Calendar calendar = null!; // initialized in helper called by ctors
 
         private int firstDayOfWeek = -1;
         private int calendarWeekRule = -1;
index b638b2a..3047109 100644 (file)
@@ -16,7 +16,7 @@ namespace System.Globalization
     public class RegionInfo
     {
         // Name of this region (ie: es-US): serialized, the field used for deserialization
-        private string _name = null!;
+        private string _name;
 
         // The CultureData instance that we are going to read data from.
         private readonly CultureData _cultureData;
@@ -47,7 +47,7 @@ namespace System.Globalization
                 throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), nameof(name));
             }
 
-            SetName(name);
+            _name = _cultureData.RegionName;
         }
 
         public RegionInfo(int culture)
@@ -86,12 +86,6 @@ namespace System.Globalization
             _name = _cultureData.RegionName;
         }
 
-        private void SetName(string name)
-        {
-            // Use the name of the region we found
-            _name = _cultureData.RegionName;
-        }
-
         /// <summary>
         /// This instance provides methods based on the current user settings.
         /// These settings are volatile and may change over the lifetime of the
index ef2efb9..fe5db92 100644 (file)
@@ -14,7 +14,7 @@ namespace System.Globalization
     /// </summary>
     public class StringInfo
     {
-        private string _str = null!;
+        private string _str = null!; // initialized in helper called by ctors
 
         private int[]? _indexes;
 
index 56ebcdb..8d7b323 100644 (file)
@@ -11,7 +11,7 @@
 **
 ===========================================================*/
 
-using System;
+#nullable enable
 using System.Threading;
 
 namespace System
@@ -23,7 +23,7 @@ namespace System
         WaitHandle AsyncWaitHandle { get; }
 
 
-        object AsyncState { get; }
+        object? AsyncState { get; }
 
         bool CompletedSynchronously { get; }
     }
index 9bbd5a7..4d01cd0 100644 (file)
@@ -133,10 +133,10 @@ namespace System.Threading
                 //   2. if IsCancellationRequested = false, then NotifyCancellation will see that the event exists, and will call Set().
                 if (IsCancellationRequested)
                 {
-                    _kernelEvent!.Set(); // TODO-NULLABLE: The ! shouldn't be necessary due to CompareExchange initialization above.
+                    _kernelEvent!.Set(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 }
 
-                return _kernelEvent!; // TODO-NULLABLE: The ! shouldn't be necessary due to CompareExchange initialization above.
+                return _kernelEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             }
         }
 
@@ -823,6 +823,7 @@ namespace System.Threading
             // this work with a callback mechanism will add additional cost to other more common cases.
             return new ValueTask(Task.Factory.StartNew(s =>
             {
+                Debug.Assert(s is Tuple<CancellationTokenSource, long>);
                 var state = (Tuple<CancellationTokenSource, long>)s;
                 state.Item1.WaitForCallbackToComplete(state.Item2);
             }, Tuple.Create(this, id), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default));
index b00d5d6..927b8fa 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 
 namespace System.Threading.Tasks
index 3677051..7e71067 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 namespace System.Threading.Tasks
 {
     internal enum AsyncCausalityStatus
index df7c934..155b00a 100644 (file)
@@ -14,6 +14,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
@@ -51,9 +52,9 @@ namespace System.Threading.Tasks
         private int m_processingCount;
         /// <summary>Completion state for a task representing the completion of this pair.</summary>
         /// <remarks>Lazily-initialized only if the scheduler pair is shutting down or if the Completion is requested.</remarks>
-        private CompletionState m_completionState;
+        private CompletionState? m_completionState;
         /// <summary>Lazily-initialized work item for processing when targeting the default scheduler.</summary>
-        private SchedulerWorkItem m_threadPoolWorkItem;
+        private SchedulerWorkItem? m_threadPoolWorkItem;
 
         /// <summary>A constant value used to signal unlimited processing.</summary>
         private const int UNLIMITED_PROCESSING = -1;
@@ -152,7 +153,7 @@ namespace System.Threading.Tasks
         private CompletionState EnsureCompletionStateInitialized()
         {
             // ValueLock not needed, but it's ok if it's held
-            return LazyInitializer.EnsureInitialized(ref m_completionState, () => new CompletionState());
+            return LazyInitializer.EnsureInitialized<CompletionState>(ref m_completionState!, () => new CompletionState()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         }
 
         /// <summary>Gets whether completion has been requested.</summary>
@@ -211,10 +212,11 @@ namespace System.Threading.Tasks
                 cs.m_completionQueued = true;
                 ThreadPool.QueueUserWorkItem(state =>
                 {
+                    Debug.Assert(state is ConcurrentExclusiveSchedulerPair);
                     var localThis = (ConcurrentExclusiveSchedulerPair)state;
-                    Debug.Assert(!localThis.m_completionState.IsCompleted, "Completion should only happen once.");
+                    Debug.Assert(!localThis.m_completionState!.IsCompleted, "Completion should only happen once.");
 
-                    List<Exception> exceptions = localThis.m_completionState.m_exceptions;
+                    List<Exception>? exceptions = localThis.m_completionState.m_exceptions;
                     bool success = (exceptions != null && exceptions.Count > 0) ?
                         localThis.m_completionState.TrySetException(exceptions) :
                         localThis.m_completionState.TrySetResult();
@@ -229,7 +231,7 @@ namespace System.Threading.Tasks
         /// <param name="faultedTask">The faulted worker task that's initiating the shutdown.</param>
         private void FaultWithTask(Task faultedTask)
         {
-            Debug.Assert(faultedTask != null && faultedTask.IsFaulted && faultedTask.Exception.InnerExceptions.Count > 0,
+            Debug.Assert(faultedTask != null && faultedTask.IsFaulted && faultedTask.Exception!.InnerExceptions.Count > 0,
                 "Needs a task in the faulted state and thus with exceptions.");
             ContractAssertMonitorStatus(ValueLock, held: true);
 
@@ -287,7 +289,7 @@ namespace System.Threading.Tasks
 
                 // If there's no processing currently happening but there are waiting exclusive tasks,
                 // let's start processing those exclusive tasks.
-                Task processingTask = null;
+                Task? processingTask = null;
                 if (m_processingCount == 0 && exclusiveTasksAreWaiting)
                 {
                     // Launch exclusive task processing
@@ -296,17 +298,17 @@ namespace System.Threading.Tasks
                     {
                         try
                         {
-                            processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessExclusiveTasks(), this,
+                            processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessExclusiveTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                                 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
                             // the exception.  To deal with that, we need a reference to the task object, so that we can observe its exception.
                             // Hence, we separate creation and starting, so that we can store a reference to the task before we attempt QueueTask.
                         }
-                        catch
+                        catch (Exception e)
                         {
                             m_processingCount = 0;
-                            FaultWithTask(processingTask);
+                            FaultWithTask(processingTask ?? Task.FromException(e));
                         }
                     }
                 }
@@ -326,14 +328,14 @@ namespace System.Threading.Tasks
                             {
                                 try
                                 {
-                                    processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessConcurrentTasks(), this,
+                                    processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessConcurrentTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                                         default, GetCreationOptionsForTask(fairly));
                                     processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew
                                 }
-                                catch
+                                catch (Exception e)
                                 {
                                     --m_processingCount;
-                                    FaultWithTask(processingTask);
+                                    FaultWithTask(processingTask ?? Task.FromException(e));
                                 }
                             }
                         }
@@ -485,7 +487,7 @@ namespace System.Threading.Tasks
             /// <summary>Whether completion processing has been queued.</summary>
             internal bool m_completionQueued;
             /// <summary>Unrecoverable exceptions incurred while processing.</summary>
-            internal List<Exception> m_exceptions;
+            internal List<Exception>? m_exceptions;
         }
 
         /// <summary>Reusable immutable work item that can be scheduled to the thread pool to run processing.</summary>
@@ -516,7 +518,7 @@ namespace System.Threading.Tasks
         private sealed class ConcurrentExclusiveTaskScheduler : TaskScheduler
         {
             /// <summary>Cached delegate for invoking TryExecuteTaskShim.</summary>
-            private static readonly Func<object, bool> s_tryExecuteTaskShim = new Func<object, bool>(TryExecuteTaskShim);
+            private static readonly Func<object?, bool> s_tryExecuteTaskShim = new Func<object?, bool>(TryExecuteTaskShim);
             /// <summary>The parent pair.</summary>
             private readonly ConcurrentExclusiveSchedulerPair m_pair;
             /// <summary>The maximum concurrency level for the scheduler.</summary>
@@ -666,8 +668,9 @@ namespace System.Threading.Tasks
             /// This method is separated out not because of performance reasons but so that
             /// the SecuritySafeCritical attribute may be employed.
             /// </remarks>
-            private static bool TryExecuteTaskShim(object state)
+            private static bool TryExecuteTaskShim(object? state)
             {
+                Debug.Assert(state is Tuple<ConcurrentExclusiveTaskScheduler, Task>);
                 var tuple = (Tuple<ConcurrentExclusiveTaskScheduler, Task>)state;
                 return tuple.Item1.TryExecuteTask(tuple.Item2);
             }
index 0b93ee8..9e562e3 100644 (file)
@@ -10,6 +10,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
@@ -60,7 +61,7 @@ namespace System.Threading.Tasks
     [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
     public class Task<TResult> : Task
     {
-        internal TResult m_result; // The value itself, if set.
+        internal TResult m_result = default!; // The value itself, if set. // TODO-NULLABLE-GENERIC
 
         private static readonly TaskFactory<TResult> s_Factory = new TaskFactory<TResult>();
 
@@ -75,14 +76,14 @@ namespace System.Threading.Tasks
             internal static readonly Func<Task<Task>, Task<TResult>> Value = completed => (Task<TResult>)completed.Result;
         }
 
-        // Construct a promise-style task without any options. 
+        // Construct a promise-style task without any options.
         internal Task() :
             base()
         {
         }
 
         // Construct a promise-style task with state and options.  
-        internal Task(object state, TaskCreationOptions options) :
+        internal Task(object? state, TaskCreationOptions options) :
             base(state, options, promiseStyle: true)
         {
         }
@@ -209,7 +210,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)
+        public Task(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(function, state, null, default,
                 TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
@@ -230,7 +231,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)
+        public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(function, state, null, cancellationToken,
                     TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
@@ -255,7 +256,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)
+        public Task(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(function, state, Task.InternalCurrentIfAttached(creationOptions), default,
                     creationOptions, InternalTaskOptions.None, null)
         {
@@ -285,7 +286,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)
+        public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
                     creationOptions, InternalTaskOptions.None, null)
         {
@@ -300,8 +301,8 @@ namespace System.Threading.Tasks
         /// <param name="cancellationToken">The CancellationToken for the task.</param>
         /// <param name="creationOptions">Options to control the future's behavior.</param>
         /// <param name="internalOptions">Internal options to control the future's behavior.</param>
-        internal Task(Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
-            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
+        internal Task(Func<TResult> valueSelector, Task? parent, CancellationToken cancellationToken,
+            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler) :
             base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
         {
         }
@@ -316,15 +317,15 @@ namespace System.Threading.Tasks
         /// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
         /// <param name="creationOptions">Options to control the future's behavior.</param>
         /// <param name="internalOptions">Internal options to control the future's behavior.</param>
-        internal Task(Delegate valueSelector, object state, Task parent, CancellationToken cancellationToken,
-            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
+        internal Task(Delegate valueSelector, object? state, Task? parent, CancellationToken cancellationToken,
+            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler) :
             base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
         {
         }
 
 
         // Internal method used by TaskFactory<TResult>.StartNew() methods
-        internal static Task<TResult> StartNew(Task parent, Func<TResult> function, CancellationToken cancellationToken,
+        internal static Task<TResult> StartNew(Task? parent, Func<TResult> function, CancellationToken cancellationToken,
             TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
         {
             if (function == null)
@@ -337,14 +338,14 @@ namespace System.Threading.Tasks
             }
 
             // Create and schedule the future.
-            Task<TResult> f = new Task<TResult>(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
+            Task<TResult> f = new Task<TResult>(function!, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             f.ScheduleAndStart(false);
             return f;
         }
 
         // Internal method used by TaskFactory<TResult>.StartNew() methods
-        internal static Task<TResult> StartNew(Task parent, Func<object, TResult> function, object state, CancellationToken cancellationToken,
+        internal static Task<TResult> StartNew(Task? parent, Func<object?, TResult> function, object? state, CancellationToken cancellationToken,
             TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
         {
             if (function == null)
@@ -357,7 +358,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);
+            Task<TResult> f = new Task<TResult>(function!, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             f.ScheduleAndStart(false);
             return f;
@@ -377,8 +378,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                Delegate d = m_action;
-                return d != null ? d.Method.ToString() : "{null}";
+                return m_action?.Method.ToString() ?? "{null}";
             }
         }
 
@@ -408,7 +408,7 @@ namespace System.Threading.Tasks
                 // and which can be summarized more concisely with the following snippet from
                 // FinishStageTwo, omitting everything that doesn't pertain to TrySetResult.
                 Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_RAN_TO_COMPLETION);
-                ContingentProperties props = m_contingentProperties;
+                ContingentProperties? props = m_contingentProperties;
                 if (props != null)
                 {
                     NotifyParentIfPotentiallyAttachedTask();
@@ -518,7 +518,7 @@ namespace System.Threading.Tasks
                 return;
             }
 
-            if (m_action is Func<object, TResult> funcWithState)
+            if (m_action is Func<object?, TResult> funcWithState)
             {
                 m_result = funcWithState(m_stateObject);
                 return;
@@ -726,13 +726,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
-                this, continuationAction, null,
+                this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationTask;
         }
@@ -757,7 +757,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)
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
         }
@@ -784,7 +784,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)
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
         }
@@ -813,7 +813,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)
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return ContinueWith(continuationAction, state, scheduler, default, TaskContinuationOptions.None);
         }
@@ -847,7 +847,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)
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, default, continuationOptions);
         }
@@ -891,14 +891,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,
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                                  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,
+        internal Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                                    TaskContinuationOptions continuationOptions)
         {
             if (continuationAction == null)
@@ -919,13 +919,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
-                this, continuationAction, state,
+                this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationTask;
         }
@@ -1135,13 +1135,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
-                this, continuationFunction, null,
+                this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationFuture;
         }
@@ -1169,7 +1169,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="continuationFunction"/> argument is null.
         /// </exception>
-        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state)
+        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state)
         {
             return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
         }
@@ -1199,7 +1199,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<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
             CancellationToken cancellationToken)
         {
             return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
@@ -1231,7 +1231,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="scheduler"/> argument is null.
         /// </exception>
-        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
             TaskScheduler scheduler)
         {
             return ContinueWith<TNewResult>(continuationFunction, state, scheduler, default, TaskContinuationOptions.None);
@@ -1275,7 +1275,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<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
             TaskContinuationOptions continuationOptions)
         {
             return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default, continuationOptions);
@@ -1330,14 +1330,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<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+        public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
         {
             return ContinueWith<TNewResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
         }
 
         // Same as the above overload, just with a stack mark.
-        internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+        internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
             TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
         {
             if (continuationFunction == null)
@@ -1358,13 +1358,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
-                this, continuationFunction, state,
+                this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationFuture;
         }
@@ -1381,13 +1381,14 @@ namespace System.Threading.Tasks
 
         public SystemThreadingTasks_FutureDebugView(Task<TResult> task)
         {
+            Debug.Assert(task != null);
             m_task = task;
         }
 
-        public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default; } }
-        public object AsyncState { get { return m_task.AsyncState; } }
+        public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default!; } } // TODO-NULLABLE-GENERIC
+        public object? AsyncState { get { return m_task.AsyncState; } }
         public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
-        public Exception Exception { get { return m_task.Exception; } }
+        public Exception? Exception { get { return m_task.Exception; } }
         public int Id { get { return m_task.Id; } }
         public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
         public TaskStatus Status { get { return m_task.Status; } }
index 55fab9a..cc4c938 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 
 namespace System.Threading.Tasks
@@ -32,27 +33,20 @@ namespace System.Threading.Tasks
 
         // member variables
         private CancellationToken m_defaultCancellationToken;
-        private TaskScheduler m_defaultScheduler;
+        private TaskScheduler? m_defaultScheduler;
         private TaskCreationOptions m_defaultCreationOptions;
         private TaskContinuationOptions m_defaultContinuationOptions;
 
-        private TaskScheduler DefaultScheduler
-        {
-            get
-            {
-                if (m_defaultScheduler == null) return TaskScheduler.Current;
-                else return m_defaultScheduler;
-            }
-        }
+        private TaskScheduler DefaultScheduler => m_defaultScheduler ?? TaskScheduler.Current;
 
         // sister method to above property -- avoids a TLS lookup
-        private TaskScheduler GetDefaultScheduler(Task currTask)
+        private TaskScheduler GetDefaultScheduler(Task? currTask)
         {
             if (m_defaultScheduler != null) return m_defaultScheduler;
             else if ((currTask != null)
                 && ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
                 )
-                return currTask.ExecutingTaskScheduler;
+                return currTask.ExecutingTaskScheduler!; // a "current" task must be executing, which means it must have a scheduler
             else return TaskScheduler.Default;
         }
 
@@ -116,7 +110,7 @@ namespace System.Threading.Tasks
         /// initialized to the current scheduler (see <see
         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
         /// </remarks>
-        public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
+        public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler.Current
             : this(default, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
         {
         }
@@ -187,7 +181,7 @@ namespace System.Threading.Tasks
         /// current scheduler (see <see
         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
         /// </remarks>
-        public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+        public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler? scheduler)
         {
             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
             TaskFactory.CheckCreationOptions(creationOptions);
@@ -221,7 +215,7 @@ namespace System.Threading.Tasks
         /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see> 
         /// will be used.
         /// </remarks>
-        public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
+        public TaskScheduler? Scheduler { get { return m_defaultScheduler; } }
 
         /// <summary>
         /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
@@ -264,7 +258,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> StartNew(Func<TResult> function)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -291,7 +285,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, cancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -320,7 +314,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> StartNew(Func<TResult> function, TaskCreationOptions creationOptions)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
                 creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -383,9 +377,9 @@ 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)
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -412,9 +406,9 @@ 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)
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -443,9 +437,9 @@ 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)
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
                 creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -485,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)
+        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
         {
             return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
                 creationOptions, InternalTaskOptions.None, scheduler);
@@ -498,16 +492,16 @@ namespace System.Threading.Tasks
         // Common core logic for FromAsync calls.  This minimizes the chance of "drift" between overload implementations.
         private static void FromAsyncCoreLogic(
             IAsyncResult iar,
-            Func<IAsyncResult, TResult> endFunction,
-            Action<IAsyncResult> endAction,
+            Func<IAsyncResult, TResult>? endFunction,
+            Action<IAsyncResult>? endAction,
             Task<TResult> promise,
             bool requiresSynchronization)
         {
             Debug.Assert((endFunction != null) != (endAction != null), "Expected exactly one of endFunction/endAction to be non-null");
 
-            Exception ex = null;
-            OperationCanceledException oce = null;
-            TResult result = default;
+            Exception? ex = null;
+            OperationCanceledException? oce = null;
+            TResult result = default!; // TODO-NULLABLE-GENERIC
 
             try
             {
@@ -517,7 +511,7 @@ namespace System.Threading.Tasks
                 }
                 else
                 {
-                    endAction(iar);
+                    endAction!(iar);
                 }
             }
             catch (OperationCanceledException _oce) { oce = _oce; }
@@ -636,8 +630,8 @@ namespace System.Threading.Tasks
         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
         internal static Task<TResult> FromAsyncImpl(
             IAsyncResult asyncResult,
-            Func<IAsyncResult, TResult> endFunction,
-            Action<IAsyncResult> endAction,
+            Func<IAsyncResult, TResult>? endFunction,
+            Action<IAsyncResult>? endAction,
             TaskCreationOptions creationOptions,
             TaskScheduler scheduler)
         {
@@ -654,7 +648,7 @@ namespace System.Threading.Tasks
 
             TaskFactory.CheckFromAsyncOptions(creationOptions, false);
 
-            Task<TResult> promise = new Task<TResult>((object)null, creationOptions);
+            Task<TResult> promise = new Task<TResult>((object?)null, creationOptions);
 
             if (AsyncCausalityTracer.LoggingOn)
                 AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync");
@@ -669,7 +663,7 @@ namespace System.Threading.Tasks
             {
                 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: true);
             }),
-                (object)null, null,
+                (object?)null, null,
                 default, TaskCreationOptions.None, InternalTaskOptions.None, null);
 
             if (AsyncCausalityTracer.LoggingOn)
@@ -678,9 +672,9 @@ namespace System.Threading.Tasks
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(t);
 
-            if (asyncResult.IsCompleted)
+            if (asyncResult!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
-                try { t.InternalRunSynchronously(scheduler, waitForCompletion: false); }
+                try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
             }
             else
@@ -718,8 +712,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync(
-            Func<AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, object state)
+            Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
         }
@@ -747,17 +741,17 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync(
-            Func<AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
+            Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
         }
 
         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
-        internal static Task<TResult> FromAsyncImpl(Func<AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
-            object state, TaskCreationOptions creationOptions)
+        internal static Task<TResult> FromAsyncImpl(Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+            object? state, TaskCreationOptions creationOptions)
         {
             if (beginMethod == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -772,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);
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -780,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 =>
+                var asyncResult = beginMethod!(iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -829,9 +823,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1>(
-            Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, object state)
+            TArg1 arg1, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
         }
@@ -863,18 +857,18 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1>(
-            Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, object state, TaskCreationOptions creationOptions)
+            TArg1 arg1, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
         }
 
         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
-        internal static Task<TResult> FromAsyncImpl<TArg1>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
-            TArg1 arg1, object state, TaskCreationOptions creationOptions)
+        internal static Task<TResult> FromAsyncImpl<TArg1>(Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+            TArg1 arg1, object? state, TaskCreationOptions creationOptions)
         {
             if (beginMethod == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -889,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);
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -897,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 =>
+                var asyncResult = beginMethod!(arg1, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -950,9 +944,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2>(
-            Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, TArg2 arg2, object state)
+            TArg1 arg1, TArg2 arg2, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
         }
@@ -988,18 +982,18 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2>(
-            Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+            TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
         }
 
         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
         // 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)
+        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
         {
             if (beginMethod == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -1014,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);
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -1022,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 =>
+                var asyncResult = beginMethod!(arg1, arg2, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -1079,9 +1073,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
-            Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+            TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
         }
@@ -1121,18 +1115,18 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
-            Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+            TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
         }
 
         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
-        internal static Task<TResult> FromAsyncImpl<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
-            TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+        internal static Task<TResult> FromAsyncImpl<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+            TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
         {
             if (beginMethod == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -1147,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);
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -1155,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 =>
+                var asyncResult = beginMethod!(arg1, arg2, arg3, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -1237,7 +1231,7 @@ namespace System.Threading.Tasks
             /// <summary>A reference to the object on which the begin/end methods are invoked.</summary>
             private TInstance m_thisRef;
             /// <summary>The end method.</summary>
-            private Func<TInstance, IAsyncResult, TResult> m_endMethod;
+            private Func<TInstance, IAsyncResult, TResult>? m_endMethod;
 
             /// <summary>Initializes the promise.</summary>
             /// <param name="thisRef">A reference to the object on which the begin/end methods are invoked.</param>
@@ -1260,13 +1254,13 @@ namespace System.Threading.Tasks
                 // Validate argument
                 if (asyncResult == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult);
 
-                var promise = asyncResult.AsyncState as FromAsyncTrimPromise<TInstance>;
+                var promise = asyncResult!.AsyncState as FromAsyncTrimPromise<TInstance>; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 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;
+                var thisRef = promise!.m_thisRef; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 var endMethod = promise.m_endMethod;
-                promise.m_thisRef = default;
+                promise.m_thisRef = default!; // TODO-NULLABLE-GENERIC
                 promise.m_endMethod = null;
                 if (endMethod == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
 
@@ -1274,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);
+                    promise.Complete(thisRef, endMethod!, asyncResult, requiresSynchronization: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 }
             }
 
@@ -1328,9 +1322,8 @@ namespace System.Threading.Tasks
         private static Task<TResult> CreateCanceledTask(TaskContinuationOptions continuationOptions, CancellationToken ct)
         {
             TaskCreationOptions tco;
-            InternalTaskOptions dontcare;
-            Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out dontcare);
-            return new Task<TResult>(true, default, tco, ct);
+            Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out _);
+            return new Task<TResult>(true, default!, tco, ct); // TODO-NULLABLE-GENERIC
         }
 
         //
@@ -1607,7 +1600,7 @@ namespace System.Threading.Tasks
         // Core implementation of ContinueWhenAll -- the generic version
         // Note: if you make any changes to this method, please do the same to the non-generic version too. 
         internal static Task<TResult> ContinueWhenAllImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
-            Func<Task<TAntecedentResult>[], TResult> continuationFunction, Action<Task<TAntecedentResult>[]> continuationAction,
+            Func<Task<TAntecedentResult>[], TResult>? continuationFunction, Action<Task<TAntecedentResult>[]>? continuationAction,
             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
         {
             // check arguments
@@ -1618,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);
+            Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             // Bail early if cancellation has been requested.
             if (cancellationToken.IsCancellationRequested
@@ -1637,7 +1630,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                    // use a cached delegate
                    GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
-                   continuationFunction, scheduler, cancellationToken, continuationOptions);
+                   continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
             else
             {
@@ -1646,14 +1639,14 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                    // use a cached delegate
                    GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
-                   continuationAction, scheduler, cancellationToken, continuationOptions);
+                   continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
         }
 
         // Core implementation of ContinueWhenAll -- the non-generic version
         // Note: if you make any changes to this method, please do the same to the generic version too. 
         internal static Task<TResult> ContinueWhenAllImpl(Task[] tasks,
-            Func<Task[], TResult> continuationFunction, Action<Task[]> continuationAction,
+            Func<Task[], TResult>? continuationFunction, Action<Task[]>? continuationAction,
             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
         {
             // check arguments
@@ -1664,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);
+            Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             // Bail early if cancellation has been requested.
             if (cancellationToken.IsCancellationRequested
@@ -1687,9 +1680,10 @@ namespace System.Threading.Tasks
                     (completedTasks, state) =>
                     {
                         completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
+                        Debug.Assert(state is Func<Task[], TResult>);
                         return ((Func<Task[], TResult>)state)(completedTasks.Result);
                     },
-                    continuationFunction, scheduler, cancellationToken, continuationOptions);
+                    continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
             else
             {
@@ -1701,9 +1695,10 @@ namespace System.Threading.Tasks
                    (completedTasks, state) =>
                    {
                        completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
-                       ((Action<Task[]>)state)(completedTasks.Result); return default;
+                        Debug.Assert(state is Action<Task[]>);
+                       ((Action<Task[]>)state)(completedTasks.Result); return default!; // TODO-NULLABLE-GENERIC
                    },
-                   continuationAction, scheduler, cancellationToken, continuationOptions);
+                   continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
         }
 
@@ -1980,13 +1975,13 @@ namespace System.Threading.Tasks
         // Core implementation of ContinueWhenAny, non-generic version
         // Note: if you make any changes to this method, be sure to do the same to the generic version 
         internal static Task<TResult> ContinueWhenAnyImpl(Task[] tasks,
-            Func<Task, TResult> continuationFunction, Action<Task> continuationAction,
+            Func<Task, TResult>? continuationFunction, Action<Task>? continuationAction,
             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
         {
             // check arguments
             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
-            if (tasks.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+            if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             //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");
@@ -2009,8 +2004,12 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith(
                      //the following delegate avoids closure capture as much as possible
                      //completedTask.Result is the winning task; state == continuationAction
-                     (completedTask, state) => { return ((Func<Task, TResult>)state)(completedTask.Result); },
-                     continuationFunction, scheduler, cancellationToken, continuationOptions);
+                     (completedTask, state) =>
+                     {
+                         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
             }
             else
             {
@@ -2018,8 +2017,13 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                     //the following delegate avoids closure capture as much as possible
                     //completedTask.Result is the winning task; state == continuationAction
-                    (completedTask, state) => { ((Action<Task>)state)(completedTask.Result); return default; },
-                    continuationAction, scheduler, cancellationToken, continuationOptions);
+                    (completedTask, state) =>
+                    {
+                        Debug.Assert(state is Action<Task>);
+                        ((Action<Task>)state)(completedTask.Result);
+                        return default!; // TODO-NULLABLE-GENERIC
+                    },
+                    continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
         }
 
@@ -2027,13 +2031,13 @@ namespace System.Threading.Tasks
         // Core implementation of ContinueWhenAny, generic version
         // Note: if you make any changes to this method, be sure to do the same to the non-generic version 
         internal static Task<TResult> ContinueWhenAnyImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
-            Func<Task<TAntecedentResult>, TResult> continuationFunction, Action<Task<TAntecedentResult>> continuationAction,
+            Func<Task<TAntecedentResult>, TResult>? continuationFunction, Action<Task<TAntecedentResult>>? continuationAction,
             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
         {
             // check arguments
             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
-            if (tasks.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+            if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             //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);
@@ -2055,7 +2059,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                     // Use a cached delegate
                     GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
-                    continuationFunction, scheduler, cancellationToken, continuationOptions);
+                    continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
             else
             {
@@ -2063,7 +2067,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                     // Use a cached delegate
                     GenericDelegateCache<TAntecedentResult, TResult>.CWAnyActionDelegate,
-                    continuationAction, scheduler, cancellationToken, continuationOptions);
+                    continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
         }
     }
@@ -2074,41 +2078,45 @@ namespace System.Threading.Tasks
     internal static class GenericDelegateCache<TAntecedentResult, TResult>
     {
         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationFunction)
-        internal static Func<Task<Task>, object, TResult> CWAnyFuncDelegate =
-            (Task<Task> wrappedWinner, object state) =>
+        internal static Func<Task<Task>, object?, TResult> CWAnyFuncDelegate =
+            (Task<Task> wrappedWinner, object? state) =>
             {
+                Debug.Assert(state is Func<Task<TAntecedentResult>, TResult>);
                 var func = (Func<Task<TAntecedentResult>, TResult>)state;
                 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
                 return func(arg);
             };
 
         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationAction)
-        internal static Func<Task<Task>, object, TResult> CWAnyActionDelegate =
-            (Task<Task> wrappedWinner, object state) =>
+        internal static Func<Task<Task>, object?, TResult> CWAnyActionDelegate =
+            (Task<Task> wrappedWinner, object? state) =>
             {
+                Debug.Assert(state is Action<Task<TAntecedentResult>>);
                 var action = (Action<Task<TAntecedentResult>>)state;
                 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
                 action(arg);
-                return default;
+                return default!; // TODO-NULLABLE-GENERIC
             };
 
         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationFunction)
-        internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllFuncDelegate =
-            (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
+        internal static Func<Task<Task<TAntecedentResult>[]>, object?, TResult> CWAllFuncDelegate =
+            (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object? state) =>
             {
                 wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
+                Debug.Assert(state is Func<Task<TAntecedentResult>>);
                 var func = (Func<Task<TAntecedentResult>[], TResult>)state;
                 return func(wrappedAntecedents.Result);
             };
 
         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationAction)
-        internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllActionDelegate =
-            (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
+        internal static Func<Task<Task<TAntecedentResult>[]>, object?, TResult> CWAllActionDelegate =
+            (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object? state) =>
             {
                 wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
+                Debug.Assert(state is Action<Task<TAntecedentResult>[]>);
                 var action = (Action<Task<TAntecedentResult>[]>)state;
                 action(wrappedAntecedents.Result);
-                return default;
+                return default!; // TODO-NULLABLE-GENERIC
             };
     }
 }
index 1880288..21214e8 100644 (file)
@@ -21,6 +21,7 @@
 // ************</IMPORTANT NOTE>*************
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System.Collections;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -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
+                array[first] = default!; // Clear the slot to release the element  // TODO-NULLABLE-GENERIC
                 segment.m_state.m_first = (first + 1) & (array.Length - 1);
                 return true;
             }
@@ -239,12 +240,12 @@ namespace System.Threading.Tasks
 
             if (first == segment.m_state.m_last)
             {
-                result = default;
+                result = default!; // TODO-NULLABLE-GENERIC
                 return false;
             }
 
             result = array[first];
-            array[first] = default; // Clear the slot to release the element
+            array[first] = default!; // Clear the slot to release the element  // TODO-NULLABLE-GENERIC
             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
 
@@ -269,7 +270,7 @@ namespace System.Threading.Tasks
         /// <remarks>WARNING: This should only be used for debugging purposes.  It is not safe to be used concurrently.</remarks>
         public IEnumerator<T> GetEnumerator()
         {
-            for (Segment segment = m_head; segment != null; segment = segment.m_next)
+            for (Segment? segment = m_head; segment != null; segment = segment.m_next)
             {
                 for (int pt = segment.m_state.m_first;
                     pt != segment.m_state.m_last;
@@ -290,7 +291,7 @@ namespace System.Threading.Tasks
             get
             {
                 int count = 0;
-                for (Segment segment = m_head; segment != null; segment = segment.m_next)
+                for (Segment? segment = m_head; segment != null; segment = segment.m_next)
                 {
                     int arraySize = segment.m_array.Length;
                     int first, last;
@@ -311,7 +312,7 @@ namespace System.Threading.Tasks
         private sealed class Segment
         {
             /// <summary>The next segment in the linked list of segments.</summary>
-            internal Segment m_next;
+            internal Segment? m_next;
             /// <summary>The data stored in this segment.</summary>
             internal readonly T[] m_array;
             /// <summary>Details about the segment.</summary>
index e411146..6181ab2 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 namespace System.Threading.Tasks.Sources
 {
     /// <summary>
@@ -53,7 +54,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);
+        void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
 
         /// <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 +74,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);
+        void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
 
         /// <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>
index 797ed6e..967cbbe 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Runtime.ExceptionServices;
 using System.Runtime.InteropServices;
@@ -18,22 +19,22 @@ namespace System.Threading.Tasks.Sources
         /// or <see cref="ManualResetValueTaskSourceCoreShared.s_sentinel"/> if the operation completed before a callback was supplied,
         /// or null if a callback hasn't yet been provided and the operation hasn't yet completed.
         /// </summary>
-        private Action<object> _continuation;
+        private Action<object?>? _continuation;
         /// <summary>State to pass to <see cref="_continuation"/>.</summary>
-        private object _continuationState;
+        private object? _continuationState;
         /// <summary><see cref="ExecutionContext"/> to flow to the callback, or null if no flowing is required.</summary>
-        private ExecutionContext _executionContext;
+        private ExecutionContext? _executionContext;
         /// <summary>
         /// A "captured" <see cref="SynchronizationContext"/> or <see cref="TaskScheduler"/> with which to invoke the callback,
         /// or null if no special context is required.
         /// </summary>
-        private object _capturedContext;
+        private object? _capturedContext;
         /// <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;
         /// <summary>The exception with which the operation failed, or null if it hasn't yet completed or completed successfully.</summary>
-        private ExceptionDispatchInfo _error;
+        private ExceptionDispatchInfo? _error;
         /// <summary>The current version of this value, used to help prevent misuse.</summary>
         private short _version;
 
@@ -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;
+            _result = default!; // TODO-NULLABLE-GENERIC
             _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)
+        public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             if (continuation == null)
             {
@@ -121,7 +122,7 @@ namespace System.Threading.Tasks.Sources
 
             if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) != 0)
             {
-                SynchronizationContext sc = SynchronizationContext.Current;
+                SynchronizationContext? sc = SynchronizationContext.Current;
                 if (sc != null && sc.GetType() != typeof(SynchronizationContext))
                 {
                     _capturedContext = sc;
@@ -144,7 +145,7 @@ namespace System.Threading.Tasks.Sources
             // To minimize the chances of that, we check preemptively whether _continuation
             // is already set to something other than the completion sentinel.
 
-            object oldContinuation = _continuation;
+            object? oldContinuation = _continuation;
             if (oldContinuation == null)
             {
                 _continuationState = state;
@@ -175,7 +176,7 @@ namespace System.Threading.Tasks.Sources
                     case SynchronizationContext sc:
                         sc.Post(s =>
                         {
-                            var tuple = (Tuple<Action<object>, object>)s;
+                            var tuple = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                             tuple.Item1(tuple.Item2);
                         }, Tuple.Create(continuation, state));
                         break;
@@ -229,6 +230,8 @@ namespace System.Threading.Tasks.Sources
         /// </summary>
         private void InvokeContinuation()
         {
+            Debug.Assert(_continuation != null);
+
             switch (_capturedContext)
             {
                 case null:
@@ -252,7 +255,7 @@ namespace System.Threading.Tasks.Sources
                 case SynchronizationContext sc:
                     sc.Post(s =>
                     {
-                        var state = (Tuple<Action<object>, object>)s;
+                        var state = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                         state.Item1(state.Item2);
                     }, Tuple.Create(_continuation, _continuationState));
                     break;
@@ -266,8 +269,8 @@ namespace System.Threading.Tasks.Sources
 
     internal static class ManualResetValueTaskSourceCoreShared // separated out of generic to avoid unnecessary duplication
     {
-        internal static readonly Action<object> s_sentinel = CompletionSentinel;
-        private static void CompletionSentinel(object _) // named method to aid debugging
+        internal static readonly Action<object?> s_sentinel = CompletionSentinel;
+        private static void CompletionSentinel(object? _) // named method to aid debugging
         {
             Debug.Fail("The sentinel delegate should never be invoked.");
             ThrowHelper.ThrowInvalidOperationException();
index 5d893c5..a8aac04 100644 (file)
@@ -10,6 +10,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
@@ -130,13 +131,13 @@ namespace System.Threading.Tasks
     public class Task : IAsyncResult, IDisposable
     {
         [ThreadStatic]
-        internal static Task t_currentTask;  // The currently executing task.
+        internal static Task? t_currentTask;  // The currently executing task.
 
         internal static int s_taskIdCounter; //static counter used to generate unique task IDs
 
         private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested
 
-        internal Delegate m_action;    // The body of the task.  Might be Action<object>, Action<TState> or Action.  Or possibly a Func.
+        internal Delegate? m_action;    // The body of the task.  Might be Action<object>, Action<TState> or Action.  Or possibly a Func.
         // If m_action is set to null it will indicate that we operate in the
         // "externally triggered completion" mode, which is exclusively meant 
         // for the signalling Task<TResult> (aka. promise). In this mode,
@@ -145,12 +146,12 @@ namespace System.Threading.Tasks
         // But the event would now be signalled if Cancel() is called
 
 
-        internal object m_stateObject; // A state object that can be optionally supplied, passed to action.
-        internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under. 
+        internal object? m_stateObject; // A state object that can be optionally supplied, passed to action.
+        internal TaskScheduler? m_taskScheduler; // The task scheduler this task runs under. 
 
         internal volatile int m_stateFlags; // SOS DumpAsync command depends on this name
 
-        private Task ParentForDebugger => m_contingentProperties?.m_parent; // Private property used by a debugger to access this Task's parent
+        private Task? ParentForDebugger => m_contingentProperties?.m_parent; // Private property used by a debugger to access this Task's parent
         private int StateFlagsForDebugger => m_stateFlags; // Private property used by a debugger to access this Task's state flags
 
         // State constants for m_stateFlags;
@@ -188,7 +189,7 @@ namespace System.Threading.Tasks
 
         // Can be null, a single continuation, a list of continuations, or s_taskCompletionSentinel,
         // in that order. The logic arround this object assumes it will never regress to a previous state.
-        private volatile object m_continuationObject = null; // SOS DumpAsync command depends on this name
+        private volatile object? m_continuationObject = null; // SOS DumpAsync command depends on this name
 
         // m_continuationObject is set to this when the task completes.
         private static readonly object s_taskCompletionSentinel = new object();
@@ -199,7 +200,7 @@ namespace System.Threading.Tasks
 
         // This dictonary relates the task id, from an operation id located in the Async Causality log to the actual
         // task. This is to be used by the debugger ONLY. Task in this dictionary represent current active tasks.
-        private static Dictionary<int, Task> s_currentActiveTasks;
+        private static Dictionary<int, Task>? s_currentActiveTasks;
 
         // These methods are a way to access the dictionary both from this class and for other classes that also
         // activate dummy tasks. Specifically the AsyncTaskMethodBuilder and AsyncTaskMethodBuilder<>
@@ -210,9 +211,9 @@ namespace System.Threading.Tasks
             LazyInitializer.EnsureInitialized(ref s_currentActiveTasks, () => new Dictionary<int, Task>());
 
             int taskId = task.Id;
-            lock (s_currentActiveTasks)
+            lock (s_currentActiveTasks!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             {
-                s_currentActiveTasks[taskId] = task;
+                s_currentActiveTasks![taskId] = task; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             }
             //always return true to keep signature as bool for backwards compatibility
             return true;
@@ -238,17 +239,17 @@ namespace System.Threading.Tasks
         {
             // Additional context
 
-            internal ExecutionContext m_capturedContext; // The execution context to run the task within, if any. Only set from non-concurrent contexts.
+            internal ExecutionContext? m_capturedContext; // The execution context to run the task within, if any. Only set from non-concurrent contexts.
 
             // Completion fields (exceptions and event)
 
-            internal volatile ManualResetEventSlim m_completionEvent; // Lazily created if waiting is required.
-            internal volatile TaskExceptionHolder m_exceptionsHolder; // Tracks exceptions, if any have occurred
+            internal volatile ManualResetEventSlim? m_completionEvent; // Lazily created if waiting is required.
+            internal volatile TaskExceptionHolder? m_exceptionsHolder; // Tracks exceptions, if any have occurred
 
             // Cancellation fields (token, registration, and internally requested)
 
             internal CancellationToken m_cancellationToken; // Task's cancellation token, if it has one
-            internal Shared<CancellationTokenRegistration> m_cancellationRegistration; // Task's registration with the cancellation token
+            internal Shared<CancellationTokenRegistration>? m_cancellationRegistration; // Task's registration with the cancellation token
             internal volatile int m_internalCancellationRequested; // Its own field because multiple threads legally try to set it.
 
             // Parenting fields
@@ -260,9 +261,9 @@ namespace System.Threading.Tasks
             internal volatile int m_completionCountdown = 1;
             // A list of child tasks that threw an exception (TCEs don't count),
             // but haven't yet been waited on by the parent, lazily initialized.
-            internal volatile List<Task> m_exceptionalChildren;
+            internal volatile List<Task>? m_exceptionalChildren;
             // A task's parent, or null if parent-less. Only set during Task construction.
-            internal Task m_parent;
+            internal Task? m_parent;
 
             /// <summary>
             /// Sets the internal completion event.
@@ -295,7 +296,7 @@ namespace System.Threading.Tasks
 
         // This field will only be instantiated to some non-null value if any ContingentProperties need to be set.
         // This will be a ContingentProperties instance or a type derived from it
-        internal ContingentProperties m_contingentProperties;
+        internal ContingentProperties? m_contingentProperties;
 
         // Special internal constructor to create an already-completed task.
         // if canceled==true, create a Canceled task, or else create a RanToCompletion task.
@@ -325,7 +326,7 @@ namespace System.Threading.Tasks
         // Special constructor for use with promise-style tasks.
         // Added promiseStyle parameter as an aid to the compiler to distinguish between (state,TCO) and
         // (action,TCO).  It should always be true.
-        internal Task(object state, TaskCreationOptions creationOptions, bool promiseStyle)
+        internal Task(object? state, TaskCreationOptions creationOptions, bool promiseStyle)
         {
             Debug.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");
 
@@ -339,7 +340,7 @@ namespace System.Threading.Tasks
             // Only set a parent if AttachedToParent is specified.
             if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
             {
-                Task parent = Task.InternalCurrent;
+                Task? parent = Task.InternalCurrent;
                 if (parent != null)
                 {
                     EnsureContingentPropertiesInitializedUnsafe().m_parent = parent;
@@ -427,7 +428,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)
+        public Task(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(action, state, null, default, TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
         }
@@ -444,7 +445,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)
+        public Task(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
         }
@@ -465,7 +466,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)
+        public Task(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null)
         {
         }
@@ -490,7 +491,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)
+        public Task(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             : this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
         {
         }
@@ -505,8 +506,8 @@ namespace System.Threading.Tasks
         /// <param name="scheduler">A task scheduler under which the task will run.</param>
         /// <param name="creationOptions">Options to control its execution.</param>
         /// <param name="internalOptions">Internal options to control its execution</param>
-        internal Task(Delegate action, object state, Task parent, CancellationToken cancellationToken,
-            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+        internal Task(Delegate action, object? state, Task? parent, CancellationToken cancellationToken,
+            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler)
         {
             if (action == null)
             {
@@ -537,8 +538,8 @@ namespace System.Threading.Tasks
         /// <param name="cancellationToken">A CancellationToken for the Task.</param>
         /// <param name="creationOptions">Options to customize behavior of Task.</param>
         /// <param name="internalOptions">Internal options to customize behavior of Task.</param>
-        internal void TaskConstructorCore(Delegate action, object state, CancellationToken cancellationToken,
-            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+        internal void TaskConstructorCore(Delegate? action, object? state, CancellationToken cancellationToken,
+            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler)
         {
             m_action = action;
             m_stateObject = state;
@@ -580,10 +581,10 @@ namespace System.Threading.Tasks
             // We can safely call the creator task's AddNewChild() method to register it, 
             // because at this point we are already on its thread of execution.
 
-            ContingentProperties props = m_contingentProperties;
+            ContingentProperties? props = m_contingentProperties;
             if (props != null)
             {
-                Task parent = props.m_parent;
+                Task? parent = props.m_parent;
                 if (parent != null
                     && ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
                     && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0))
@@ -606,7 +607,7 @@ namespace System.Threading.Tasks
         /// Handles everything needed for associating a CancellationToken with a task which is being constructed.
         /// This method is meant to be called either from the TaskConstructorCore or from ContinueWithCore.
         /// </summary>
-        private void AssignCancellationToken(CancellationToken cancellationToken, Task antecedent, TaskContinuation continuation)
+        private void AssignCancellationToken(CancellationToken cancellationToken, Task? antecedent, TaskContinuation? continuation)
         {
             // There is no need to worry about concurrency issues here because we are in the constructor path of the task --
             // there should not be any race conditions to set m_contingentProperties at this point.
@@ -634,16 +635,18 @@ 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);
+                            ctr = cancellationToken.UnsafeRegister(t => ((Task)t!).InternalCancel(false), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                         }
                         else
                         {
+                            Debug.Assert(continuation != null);
+
                             // If an antecedent was specified, pack this task, its antecedent and the TaskContinuation together as a tuple 
                             // and use it as the cancellation state object. This will be unpacked in the cancellation callback so that 
                             // antecedent.RemoveCancellation(continuation) can be invoked.
                             ctr = cancellationToken.UnsafeRegister(t =>
                             {
-                                var tuple = (Tuple<Task, Task, TaskContinuation>)t;
+                                var tuple = (Tuple<Task, Task, TaskContinuation>)t!;
             
                                 Task targetTask = tuple.Item1;
                                 Task antecedentTask = tuple.Item2;
@@ -662,7 +665,7 @@ namespace System.Threading.Tasks
             {
                 // If we have an exception related to our CancellationToken, then we need to subtract ourselves
                 // from our parent before throwing it.
-                Task parent = m_contingentProperties?.m_parent;
+                Task? parent = m_contingentProperties?.m_parent;
                 if ((parent != null) &&
                     ((Options & TaskCreationOptions.AttachedToParent) != 0)
                      && ((parent.Options & TaskCreationOptions.DenyChildAttach) == 0))
@@ -678,8 +681,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                Delegate d = m_action;
-                return d != null ? d.Method.ToString() : "{null}";
+                return m_action?.Method.ToString() ?? "{null}";
             }
         }
 
@@ -787,7 +789,7 @@ namespace System.Threading.Tasks
         /// <summary>Returns true if any of the supplied tasks require wait notification.</summary>
         /// <param name="tasks">The tasks to check.</param>
         /// <returns>true if any of the tasks require notification; otherwise, false.</returns>
-        internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task[] tasks)
+        internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task?[] tasks)
         {
             Debug.Assert(tasks != null, "Expected non-null array of tasks");
             foreach (var task in tasks)
@@ -871,8 +873,8 @@ namespace System.Threading.Tasks
             {
                 m_stateFlags |= Task.TASK_STATE_TASKSCHEDULED_WAS_FIRED;
 
-                Task currentTask = Task.InternalCurrent;
-                Task parentTask = m_contingentProperties?.m_parent;
+                Task? currentTask = Task.InternalCurrent;
+                Task? parentTask = m_contingentProperties?.m_parent;
                 TplEventSource.Log.TaskScheduled(ts.Id, currentTask == null ? 0 : currentTask.Id,
                                      this.Id, parentTask == null ? 0 : parentTask.Id, (int)this.Options);
             }
@@ -1049,7 +1051,7 @@ namespace System.Threading.Tasks
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
             }
 
-            InternalRunSynchronously(scheduler, waitForCompletion: true);
+            InternalRunSynchronously(scheduler!, waitForCompletion: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
         }
 
         //
@@ -1158,7 +1160,7 @@ namespace System.Threading.Tasks
 
         // Implicitly converts action to object and handles the meat of the StartNew() logic.
         internal static Task InternalStartNew(
-            Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
+            Task? creatingTask, Delegate action, object? state, CancellationToken cancellationToken, TaskScheduler scheduler,
             TaskCreationOptions options, InternalTaskOptions internalOptions)
         {
             // Validate arguments.
@@ -1227,7 +1229,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                Task currentTask = InternalCurrent;
+                Task? currentTask = InternalCurrent;
                 if (currentTask != null)
                     return currentTask.Id;
                 else
@@ -1239,7 +1241,7 @@ namespace System.Threading.Tasks
         /// Gets the <see cref="Task">Task</see> instance currently executing, or
         /// null if none exists.
         /// </summary>
-        internal static Task InternalCurrent
+        internal static Task? InternalCurrent
         {
             get { return t_currentTask; }
         }
@@ -1250,7 +1252,7 @@ namespace System.Threading.Tasks
         /// </summary>
         /// <param name="creationOptions">The options to check.</param>
         /// <returns>The current task if there is one and if AttachToParent is in the options; otherwise, null.</returns>
-        internal static Task InternalCurrentIfAttached(TaskCreationOptions creationOptions)
+        internal static Task? InternalCurrentIfAttached(TaskCreationOptions creationOptions)
         {
             return (creationOptions & TaskCreationOptions.AttachedToParent) != 0 ? InternalCurrent : null;
         }
@@ -1267,11 +1269,11 @@ namespace System.Threading.Tasks
         /// or in accesses to the <see cref="Exception"/> property.  Any exceptions not observed by the time
         /// the Task instance is garbage collected will be propagated on the finalizer thread.
         /// </remarks>
-        public AggregateException Exception
+        public AggregateException? Exception
         {
             get
             {
-                AggregateException e = null;
+                AggregateException? e = null;
 
                 // If you're faulted, retrieve the exception(s)
                 if (IsFaulted) e = GetExceptions(false);
@@ -1355,7 +1357,7 @@ namespace System.Threading.Tasks
         /// <returns>The initialized contingent properties object.</returns>
         internal ContingentProperties EnsureContingentPropertiesInitialized()
         {
-            return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties());
+            return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties())!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         }
 
         /// <summary>
@@ -1460,7 +1462,7 @@ namespace System.Threading.Tasks
         /// Gets the state object supplied when the <see cref="Task">Task</see> was created,
         /// or null if none was supplied.
         /// </summary>
-        public object AsyncState
+        public object? AsyncState
         {
             get { return m_stateObject; }
         }
@@ -1480,7 +1482,7 @@ namespace System.Threading.Tasks
         /// <summary>
         /// Provides access to the TaskScheduler responsible for executing this Task.
         /// </summary>
-        internal TaskScheduler ExecutingTaskScheduler
+        internal TaskScheduler? ExecutingTaskScheduler
         {
             get { return m_taskScheduler; }
         }
@@ -1524,13 +1526,13 @@ namespace System.Threading.Tasks
                     }
                 }
 
-                return contingentProps.m_completionEvent;
+                return contingentProps.m_completionEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             }
         }
 
 
         /// <summary>
-        /// The property formerly known as IsFaulted.
+        /// Whether an exception has been stored into the task.
         /// </summary>
         internal bool ExceptionRecorded
         {
@@ -1563,7 +1565,7 @@ namespace System.Threading.Tasks
         /// If the TASK_STATE_EXECUTIONCONTEXT_IS_NULL flag is set, this means ExecutionContext.Capture returned null, otherwise
         /// If the captured context is the default, nothing is saved, otherwise the m_contingentProperties inflates to save the context
         /// </summary>
-        internal ExecutionContext CapturedContext
+        internal ExecutionContext? CapturedContext
         {
             get
             {
@@ -1716,6 +1718,7 @@ namespace System.Threading.Tasks
             if (AsyncCausalityTracer.LoggingOn && (Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
             {
                 //For all other task than TaskContinuations we want to log. TaskContinuations log in their constructor
+                Debug.Assert(m_action != null, "Must have a delegate to be in ScheduleAndStart");
                 AsyncCausalityTracer.TraceOperationCreation(this, "Task: " + m_action.Method.Name);
             }
 
@@ -1813,7 +1816,7 @@ namespace System.Threading.Tasks
 
             lock (props)
             {
-                props.m_exceptionsHolder.Add(exceptionObject, representsCancellation);
+                props.m_exceptionsHolder!.Add(exceptionObject, representsCancellation); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             }
         }
 
@@ -1823,7 +1826,7 @@ namespace System.Threading.Tasks
         /// </summary>
         /// <param name="includeTaskCanceledExceptions">Whether to include a TCE if cancelled.</param>
         /// <returns>An aggregate exception, or null if no exceptions have been caught.</returns>
-        private AggregateException GetExceptions(bool includeTaskCanceledExceptions)
+        private AggregateException? GetExceptions(bool includeTaskCanceledExceptions)
         {
             //
             // WARNING: The Task/Task<TResult>/TaskCompletionSource classes
@@ -1861,7 +1864,7 @@ namespace System.Threading.Tasks
             //
 
             // We'll lazily create a TCE if the task has been canceled.
-            Exception canceledException = null;
+            Exception? canceledException = null;
             if (includeTaskCanceledExceptions && IsCanceled)
             {
                 // Backcompat: 
@@ -1877,7 +1880,7 @@ namespace System.Threading.Tasks
             {
                 // There are exceptions; get the aggregate and optionally add the canceled
                 // exception to the aggregate (if applicable).
-                Debug.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
+                Debug.Assert(m_contingentProperties != null && m_contingentProperties.m_exceptionsHolder != null, "ExceptionRecorded should imply this");
 
                 // No need to lock around this, as other logic prevents the consumption of exceptions
                 // before they have been completely processed.
@@ -1898,13 +1901,13 @@ namespace System.Threading.Tasks
             bool exceptionsAvailable = IsFaulted && ExceptionRecorded;
             Debug.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions.");
             return exceptionsAvailable ?
-                m_contingentProperties.m_exceptionsHolder.GetExceptionDispatchInfos() :
+                m_contingentProperties!.m_exceptionsHolder!.GetExceptionDispatchInfos() :
                 new ReadOnlyCollection<ExceptionDispatchInfo>(new ExceptionDispatchInfo[0]);
         }
 
         /// <summary>Gets the ExceptionDispatchInfo containing the OperationCanceledException for this task.</summary>
         /// <returns>The ExceptionDispatchInfo.  May be null if no OCE was stored for the task.</returns>
-        internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
+        internal ExceptionDispatchInfo? GetCancellationExceptionDispatchInfo()
         {
             Debug.Assert(IsCanceled, "Must only be used when the task has canceled.");
             return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null
@@ -1917,7 +1920,7 @@ namespace System.Threading.Tasks
         {
             Debug.Assert(IsCompleted, "ThrowIfExceptional(): Expected IsCompleted == true");
 
-            Exception exception = GetExceptions(includeTaskCanceledExceptions);
+            Exception? exception = GetExceptions(includeTaskCanceledExceptions);
             if (exception != null)
             {
                 UpdateExceptionObservedStatus();
@@ -1928,7 +1931,7 @@ namespace System.Threading.Tasks
         /// <summary>Throws the exception on the ThreadPool.</summary>
         /// <param name="exception">The exception to propagate.</param>
         /// <param name="targetContext">The target context on which to propagate the exception.  Null to use the ThreadPool.</param>
-        internal static void ThrowAsync(Exception exception, SynchronizationContext targetContext)
+        internal static void ThrowAsync(Exception exception, SynchronizationContext? targetContext)
         {
             // Capture the exception into an ExceptionDispatchInfo so that its 
             // stack trace and Watson bucket info will be preserved
@@ -1940,7 +1943,7 @@ namespace System.Threading.Tasks
                 try
                 {
                     // Post the throwing of the exception to that context, and return.
-                    targetContext.Post(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+                    targetContext.Post(state => ((ExceptionDispatchInfo)state!).Throw(), edi);
                     return;
                 }
                 catch (Exception postException)
@@ -1962,7 +1965,7 @@ namespace System.Threading.Tasks
 #endif
 
             // Propagate the exception(s) on the ThreadPool
-            ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+            ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state!).Throw(), edi);
 
 #endif // CORERT
         }
@@ -1980,7 +1983,7 @@ namespace System.Threading.Tasks
         /// </summary>
         internal void UpdateExceptionObservedStatus()
         {
-            Task parent = m_contingentProperties?.m_parent;
+            Task? parent = m_contingentProperties?.m_parent;
             if ((parent != null)
                 && ((Options & TaskCreationOptions.AttachedToParent) != 0)
                 && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
@@ -2048,7 +2051,7 @@ namespace System.Threading.Tasks
             }
             else
             {
-                ContingentProperties props = m_contingentProperties;
+                ContingentProperties props = m_contingentProperties!;
 
                 // Count of 1 => either all children finished, or there were none. Safe to complete ourselves 
                 // without paying the price of an Interlocked.Decrement.
@@ -2075,7 +2078,7 @@ namespace System.Threading.Tasks
 
                 // Now is the time to prune exceptional children. We'll walk the list and removes the ones whose exceptions we might have observed after they threw.
                 // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren 
-                List<Task> exceptionalChildren = props.m_exceptionalChildren;
+                List<Task>? exceptionalChildren = props.m_exceptionalChildren;
                 if (exceptionalChildren != null)
                 {
                     lock (exceptionalChildren)
@@ -2096,7 +2099,7 @@ namespace System.Threading.Tasks
             // At this point, the task is done executing and waiting for its children,
             // we can transition our task to a completion state.  
 
-            ContingentProperties cp = Volatile.Read(ref m_contingentProperties);
+            ContingentProperties? cp = Volatile.Read(ref m_contingentProperties);
             if (cp != null)
             {
                 AddExceptionsFromChildren(cp);
@@ -2170,7 +2173,7 @@ namespace System.Threading.Tasks
             // continuations hold onto the task, and therefore are keeping it alive.
             m_action = null;
 
-            ContingentProperties cp = m_contingentProperties;
+            ContingentProperties? cp = m_contingentProperties;
             if (cp != null)
             {
                 // Similarly, null out any ExecutionContext we may have captured,
@@ -2188,7 +2191,7 @@ namespace System.Threading.Tasks
 
         internal void NotifyParentIfPotentiallyAttachedTask()
         {
-            Task parent = m_contingentProperties?.m_parent;
+            Task? parent = m_contingentProperties?.m_parent;
             if (parent != null
                  && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
                  && (((TaskCreationOptions)(m_stateFlags & OptionsMask)) & TaskCreationOptions.AttachedToParent) != 0)
@@ -2213,7 +2216,7 @@ namespace System.Threading.Tasks
             if (childTask.IsFaulted && !childTask.IsExceptionObservedByParent)
             {
                 // Lazily initialize the child exception list
-                if (props.m_exceptionalChildren == null)
+                if (props!.m_exceptionalChildren == null)
                 {
                     Interlocked.CompareExchange(ref props.m_exceptionalChildren, new List<Task>(), null);
                 }
@@ -2222,7 +2225,7 @@ namespace System.Threading.Tasks
                 // multiple times for the same task.  In that case, AddExceptionsFromChildren() could be nulling m_exceptionalChildren
                 // out at the same time that we're processing it, resulting in a NullReferenceException here.  We'll protect
                 // ourselves by caching m_exceptionChildren in a local variable.
-                List<Task> tmp = props.m_exceptionalChildren;
+                List<Task>? tmp = props.m_exceptionalChildren;
                 if (tmp != null)
                 {
                     lock (tmp)
@@ -2232,7 +2235,7 @@ namespace System.Threading.Tasks
                 }
             }
 
-            if (Interlocked.Decrement(ref props.m_completionCountdown) == 0)
+            if (Interlocked.Decrement(ref props!.m_completionCountdown) == 0)
             {
                 // This call came from the final child to complete, and apparently we have previously given up this task's right to complete itself.
                 // So we need to invoke the final finish stage.
@@ -2253,7 +2256,7 @@ namespace System.Threading.Tasks
             // simultaneously on the same task from two different contexts.  This can result in m_exceptionalChildren
             // being nulled out while it is being processed, which could lead to a NullReferenceException.  To
             // protect ourselves, we'll cache m_exceptionalChildren in a local variable.
-            List<Task> exceptionalChildren = props.m_exceptionalChildren;
+            List<Task>? exceptionalChildren = props.m_exceptionalChildren;
 
             if (exceptionalChildren != null)
             {
@@ -2268,7 +2271,7 @@ namespace System.Threading.Tasks
                         Debug.Assert(task.IsCompleted, "Expected all tasks in list to be completed");
                         if (task.IsFaulted && !task.IsExceptionObservedByParent)
                         {
-                            TaskExceptionHolder exceptionHolder = Volatile.Read(ref task.m_contingentProperties).m_exceptionsHolder;
+                            TaskExceptionHolder? exceptionHolder = Volatile.Read(ref task.m_contingentProperties)!.m_exceptionsHolder;
                             Debug.Assert(exceptionHolder != null);
 
                             // No locking necessary since child task is finished adding exceptions
@@ -2322,7 +2325,7 @@ namespace System.Threading.Tasks
         /// </summary>
         internal virtual void ExecuteFromThreadPool(Thread threadPoolThread) => ExecuteEntryUnsafe(threadPoolThread);
 
-        internal void ExecuteEntryUnsafe(Thread threadPoolThread) // used instead of ExecuteEntry() when we don't have to worry about double-execution prevent
+        internal void ExecuteEntryUnsafe(Thread? threadPoolThread) // used instead of ExecuteEntry() when we don't have to worry about double-execution prevent
         {
             // Remember that we started running the task delegate.
             m_stateFlags |= TASK_STATE_DELEGATE_INVOKED;
@@ -2350,10 +2353,10 @@ namespace System.Threading.Tasks
         }
 
         // A trick so we can refer to the TLS slot with a byref.
-        private void ExecuteWithThreadLocal(ref Task currentTaskSlot, Thread threadPoolThread = null)
+        private void ExecuteWithThreadLocal(ref Task? currentTaskSlot, Thread? threadPoolThread = null)
         {
             // Remember the current task so we can restore it after running, and then
-            Task previousTask = currentTaskSlot;
+            Task? previousTask = currentTaskSlot;
 
             // ETW event for Task Started
             var log = TplEventSource.Log;
@@ -2365,7 +2368,7 @@ namespace System.Threading.Tasks
                     EventSource.SetCurrentThreadActivityId(TplEventSource.CreateGuidForTaskID(this.Id), out savedActivityID);
                 // previousTask holds the actual "current task" we want to report in the event
                 if (previousTask != null)
-                    log.TaskStarted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id);
+                    log.TaskStarted(previousTask.m_taskScheduler!.Id, previousTask.Id, this.Id);
                 else
                     log.TaskStarted(TaskScheduler.Current.Id, 0, this.Id);
             }
@@ -2382,7 +2385,7 @@ namespace System.Threading.Tasks
                 // Execute the task body
                 try
                 {
-                    ExecutionContext ec = CapturedContext;
+                    ExecutionContext? ec = CapturedContext;
                     if (ec == null)
                     {
                         // No context, just run the task directly.
@@ -2421,7 +2424,7 @@ namespace System.Threading.Tasks
                 {
                     // previousTask holds the actual "current task" we want to report in the event
                     if (previousTask != null)
-                        log.TaskCompleted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id, IsFaulted);
+                        log.TaskCompleted(previousTask.m_taskScheduler!.Id, previousTask.Id, this.Id, IsFaulted);
                     else
                         log.TaskCompleted(TaskScheduler.Current.Id, 0, this.Id, IsFaulted);
 
@@ -2451,7 +2454,7 @@ namespace System.Threading.Tasks
                 return;
             }
 
-            if (m_action is Action<object> actionWithState)
+            if (m_action is Action<object?> actionWithState)
             {
                 actionWithState(m_stateObject);
                 return;
@@ -2469,7 +2472,7 @@ namespace System.Threading.Tasks
             Debug.Assert(unhandledException != null);
 
             if (unhandledException is OperationCanceledException exceptionAsOce && IsCancellationRequested &&
-                m_contingentProperties.m_cancellationToken == exceptionAsOce.CancellationToken)
+                m_contingentProperties!.m_cancellationToken == exceptionAsOce.CancellationToken)
             {
                 // All conditions are satisfied for us to go into canceled state in Finish().
                 // Mark the acknowledgement.  The exception is also stored to enable it to be
@@ -2526,7 +2529,7 @@ namespace System.Threading.Tasks
             // Create the best AwaitTaskContinuation object given the request.
             // If this remains null by the end of the function, we can use the 
             // continuationAction directly without wrapping it.
-            TaskContinuation tc = null;
+            TaskContinuation? tc = null;
 
             // If the user wants the continuation to run on the current "context" if there is one...
             if (continueOnCapturedContext)
@@ -2605,7 +2608,7 @@ namespace System.Threading.Tasks
             // fall back to using the state machine's delegate.
             if (continueOnCapturedContext)
             {
-                SynchronizationContext syncCtx = SynchronizationContext.Current;
+                SynchronizationContext? syncCtx = SynchronizationContext.Current;
                 if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
                 {
                     var tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, stateMachineBox.MoveNextAction, flowExecutionContext: false);
@@ -2617,7 +2620,7 @@ namespace System.Threading.Tasks
                 }
                 else
                 {
-                    TaskScheduler scheduler = TaskScheduler.InternalCurrent;
+                    TaskScheduler? scheduler = TaskScheduler.InternalCurrent;
                     if (scheduler != null && scheduler != TaskScheduler.Default)
                     {
                         var tc = new TaskSchedulerAwaitTaskContinuation(scheduler, stateMachineBox.MoveNextAction, flowExecutionContext: false);
@@ -2846,9 +2849,9 @@ namespace System.Threading.Tasks
             bool etwIsEnabled = log.IsEnabled();
             if (etwIsEnabled)
             {
-                Task currentTask = Task.InternalCurrent;
+                Task? currentTask = Task.InternalCurrent;
                 log.TaskWaitBegin(
-                    (currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
+                    (currentTask != null ? currentTask.m_taskScheduler!.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
                     this.Id, TplEventSource.TaskWaitBehavior.Synchronous, 0);
             }
 
@@ -2877,10 +2880,10 @@ namespace System.Threading.Tasks
             // ETW event for Task Wait End
             if (etwIsEnabled)
             {
-                Task currentTask = Task.InternalCurrent;
+                Task? currentTask = Task.InternalCurrent;
                 if (currentTask != null)
                 {
-                    log.TaskWaitEnd(currentTask.m_taskScheduler.Id, currentTask.Id, this.Id);
+                    log.TaskWaitEnd(currentTask.m_taskScheduler!.Id, currentTask.Id, this.Id);
                 }
                 else
                 {
@@ -2999,12 +3002,12 @@ namespace System.Threading.Tasks
             bool bPopSucceeded = false;
             bool mustCleanup = false;
 
-            TaskSchedulerException tse = null;
+            TaskSchedulerException? tse = null;
 
             // If started, and running in a task context, we can try to pop the chore.
             if ((m_stateFlags & TASK_STATE_STARTED) != 0)
             {
-                TaskScheduler ts = m_taskScheduler;
+                TaskScheduler? ts = m_taskScheduler;
 
                 try
                 {
@@ -3095,7 +3098,7 @@ namespace System.Threading.Tasks
             RecordInternalCancellationRequest();
 
             Debug.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task");
-            Debug.Assert(m_contingentProperties.m_cancellationToken == default);
+            Debug.Assert(m_contingentProperties!.m_cancellationToken == default);
 
             // Store the supplied cancellation token as this task's token.
             // Waiting on this task will then result in an OperationCanceledException containing this token.
@@ -3108,7 +3111,7 @@ namespace System.Threading.Tasks
         // Breaks out logic for recording a cancellation request
         // This overload should only be used for promise tasks where no cancellation token
         // was supplied when the task was created.
-        internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord, object cancellationException)
+        internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord, object? cancellationException)
         {
             RecordInternalCancellationRequest(tokenToRecord);
 
@@ -3184,7 +3187,7 @@ namespace System.Threading.Tasks
                 TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION,
                 TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
             {
-                ContingentProperties props = m_contingentProperties;
+                ContingentProperties? props = m_contingentProperties;
                 if (props != null)
                 {
                     NotifyParentIfPotentiallyAttachedTask();
@@ -3252,7 +3255,7 @@ namespace System.Threading.Tasks
         // If the tokenToRecord is not None, it will be stored onto the task.
         // If the OperationCanceledException is not null, it will be stored into the task's exception holder.
         // This method is only valid for promise tasks.
-        internal bool TrySetCanceled(CancellationToken tokenToRecord, object cancellationException)
+        internal bool TrySetCanceled(CancellationToken tokenToRecord, object? cancellationException)
         {
             Debug.Assert(m_action == null, "Task<T>.TrySetCanceled(): non-null m_action");
             Debug.Assert(
@@ -3296,7 +3299,7 @@ namespace System.Threading.Tasks
             // Atomically store the fact that this task is completing.  From this point on, the adding of continuations will
             // result in the continuations being run/launched directly rather than being added to the continuation list.
             // Then if we grabbed any continuations, run them.
-            object continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
+            object? continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
             if (continuationObject != null)
             {
                 RunContinuations(continuationObject);
@@ -3352,7 +3355,7 @@ namespace System.Threading.Tasks
             }
 
             // Not a single; it must be a list.
-            List<object> continuations = (List<object>)continuationObject;
+            List<object?> continuations = (List<object?>)continuationObject;
 
             //
             // Begin processing of continuation list
@@ -3384,7 +3387,7 @@ namespace System.Threading.Tasks
             // and Action delegates, which are all by default implicitly synchronous.
             for (int i = 0; i < continuationCount; i++)
             {
-                object currentContinuation = continuations[i];
+                object? currentContinuation = continuations[i];
                 if (currentContinuation == null)
                 {
                     continue;
@@ -3611,13 +3614,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromTask(
-                this, continuationAction, null,
+                this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationTask;
         }
@@ -3642,7 +3645,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="continuationAction"/> argument is null.
         /// </exception>
-        public Task ContinueWith(Action<Task, object> continuationAction, object state)
+        public Task ContinueWith(Action<Task, object?> continuationAction, object? state)
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
         }
@@ -3668,7 +3671,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, object> continuationAction, object state, CancellationToken cancellationToken)
+        public Task ContinueWith(Action<Task, object?> continuationAction, object? state, CancellationToken cancellationToken)
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
         }
@@ -3696,7 +3699,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="scheduler"/> argument is null.
         /// </exception>
-        public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
+        public Task ContinueWith(Action<Task, object?> continuationAction, object? state, TaskScheduler scheduler)
         {
             return ContinueWith(continuationAction, state, scheduler, default, TaskContinuationOptions.None);
         }
@@ -3730,7 +3733,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, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
+        public Task ContinueWith(Action<Task, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions)
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, default, continuationOptions);
         }
@@ -3774,14 +3777,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, object> continuationAction, object state, CancellationToken cancellationToken,
+        public Task ContinueWith(Action<Task, object?> continuationAction, object? state, CancellationToken cancellationToken,
                                  TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
         {
             return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
         }
 
         // Same as the above overload, just with a stack mark parameter.
-        private Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler,
+        private Task ContinueWith(Action<Task, object?> continuationAction, object? state, TaskScheduler scheduler,
             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
         {
             // Throw on continuation with null action
@@ -3801,13 +3804,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromTask(
-                this, continuationAction, state,
+                this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationTask;
         }
@@ -4004,13 +4007,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
-                this, continuationFunction, null,
+                this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationTask;
         }
@@ -4038,7 +4041,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="continuationFunction"/> argument is null.
         /// </exception>
-        public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state)
+        public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state)
         {
             return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default,
                 TaskContinuationOptions.None);
@@ -4069,7 +4072,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<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
+        public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, CancellationToken cancellationToken)
         {
             return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
         }
@@ -4100,7 +4103,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="scheduler"/> argument is null.
         /// </exception>
-        public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
+        public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, TaskScheduler scheduler)
         {
             return ContinueWith<TResult>(continuationFunction, state, scheduler, default, TaskContinuationOptions.None);
         }
@@ -4137,7 +4140,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<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
+        public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, TaskContinuationOptions continuationOptions)
         {
             return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default, continuationOptions);
         }
@@ -4184,14 +4187,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<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
+        public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, CancellationToken cancellationToken,
                                                    TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
         {
             return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
         }
 
         // Same as the above overload, just with a stack mark parameter.
-        private Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler,
+        private Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, TaskScheduler scheduler,
             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
         {
             // Throw on continuation with null function
@@ -4211,13 +4214,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
-                this, continuationFunction, state,
+                this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             return continuationTask;
         }
@@ -4386,13 +4389,13 @@ namespace System.Threading.Tasks
         {
             Debug.Assert(tc != null, "Expected non-null tc object in AddTaskContinuationComplex");
 
-            object oldValue = m_continuationObject;
+            object? oldValue = m_continuationObject;
 
             // Logic for the case where we were previously storing a single continuation
-            if ((oldValue != s_taskCompletionSentinel) && (!(oldValue is List<object>)))
+            if ((oldValue != s_taskCompletionSentinel) && (!(oldValue is List<object?>)))
             {
                 // Construct a new TaskContinuation list
-                List<object> newList = new List<object>();
+                List<object?> newList = new List<object?>();
 
                 // Add in the old single value
                 newList.Add(oldValue);
@@ -4407,7 +4410,7 @@ namespace System.Threading.Tasks
 
             // m_continuationObject is guaranteed at this point to be either a List or
             // s_taskCompletionSentinel.
-            List<object> list = m_continuationObject as List<object>;
+            List<object?>? list = m_continuationObject as List<object?>;
             Debug.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel),
                 "Expected m_continuationObject to be list or sentinel");
 
@@ -4469,21 +4472,21 @@ namespace System.Threading.Tasks
         {
             // We need to snap a local reference to m_continuations since reading a volatile object is more costly.
             // Also to prevent the value to be changed as result of a race condition with another method.
-            object continuationsLocalRef = m_continuationObject;
+            object? continuationsLocalRef = m_continuationObject;
 
             // Task is completed. Nothing to do here.
             if (continuationsLocalRef == s_taskCompletionSentinel) return;
 
-            if (!(continuationsLocalRef is List<object> continuationsLocalListRef))
+            if (!(continuationsLocalRef is List<object?> continuationsLocalListRef))
             {
                 // This is not a list. If we have a single object (the one we want to remove) we try to replace it with an empty list.
                 // Note we cannot go back to a null state, since it will mess up the AddTaskContinuation logic.
-                if (Interlocked.CompareExchange(ref m_continuationObject, new List<object>(), continuationObject) != continuationObject)
+                if (Interlocked.CompareExchange(ref m_continuationObject, new List<object?>(), continuationObject) != continuationObject)
                 {
                     // If we fail it means that either AddContinuationComplex won the race condition and m_continuationObject is now a List
                     // that contains the element we want to remove. Or FinishContinuations set the s_taskCompletionSentinel.
                     // So we should try to get a list one more time
-                    continuationsLocalListRef = m_continuationObject as List<object>;
+                    continuationsLocalListRef = m_continuationObject as List<object?>;
                 }
                 else
                 {
@@ -4711,9 +4714,9 @@ namespace System.Threading.Tasks
             // We make sure that the exception behavior of Task.Wait() is replicated the same for tasks handled in either of these codepaths
             //
 
-            List<Exception> exceptions = null;
-            List<Task> waitedOnTaskList = null;
-            List<Task> notificationTasks = null;
+            List<Exception>? exceptions = null;
+            List<Task>? waitedOnTaskList = null;
+            List<Task>? notificationTasks = null;
 
             // If any of the waited-upon tasks end as Faulted or Canceled, set these to true.
             bool exceptionSeen = false, cancellationSeen = false;
@@ -4721,7 +4724,7 @@ namespace System.Threading.Tasks
             bool returnValue = true;
 
             // Collects incomplete tasks in "waitedOnTaskList"
-            for (int i = tasks.Length - 1; i >= 0; i--)
+            for (int i = tasks!.Length - 1; i >= 0; i--) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 Task task = tasks[i];
 
@@ -4730,7 +4733,7 @@ namespace System.Threading.Tasks
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
                 }
 
-                bool taskIsCompleted = task.IsCompleted;
+                bool taskIsCompleted = task!.IsCompleted; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 if (!taskIsCompleted)
                 {
                     // try inlining the task only if we have an infinite timeout and an empty cancellation token
@@ -4819,7 +4822,7 @@ namespace System.Threading.Tasks
         /// <param name="item">The item to add.</param>
         /// <param name="list">The list.</param>
         /// <param name="initSize">The size to which to initialize the list if the list is null.</param>
-        private static void AddToList<T>(T item, ref List<T> list, int initSize)
+        private static void AddToList<T>(T item, ref List<T>? list, int initSize)
         {
             if (list == null) list = new List<T>(initSize);
             list.Add(item);
@@ -4897,9 +4900,9 @@ namespace System.Threading.Tasks
         /// If the completed task is canceled or it has other exceptions, here we will add those
         /// into the passed in exception list (which will be lazily initialized here).
         /// </summary>
-        internal static void AddExceptionsForCompletedTask(ref List<Exception> exceptions, Task t)
+        internal static void AddExceptionsForCompletedTask(ref List<Exception>? exceptions, Task t)
         {
-            AggregateException ex = t.GetExceptions(true);
+            AggregateException? ex = t.GetExceptions(true);
             if (ex != null)
             {
                 // make sure the task's exception observed status is set appropriately
@@ -5086,7 +5089,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++)
+            for (int taskIndex = 0; taskIndex < tasks!.Length; taskIndex++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 Task task = tasks[taskIndex];
 
@@ -5095,7 +5098,7 @@ namespace System.Threading.Tasks
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
                 }
 
-                if (signaledTaskIndex == -1 && task.IsCompleted)
+                if (signaledTaskIndex == -1 && task!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 {
                     // 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.
@@ -5147,7 +5150,7 @@ namespace System.Threading.Tasks
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
             var task = new Task();
-            bool succeeded = task.TrySetException(exception);
+            bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             Debug.Assert(succeeded, "This should always succeed on a new task.");
             return task;
         }
@@ -5161,7 +5164,7 @@ namespace System.Threading.Tasks
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
             var task = new Task<TResult>();
-            bool succeeded = task.TrySetException(exception);
+            bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             Debug.Assert(succeeded, "This should always succeed on a new task.");
             return task;
         }
@@ -5184,7 +5187,7 @@ namespace System.Threading.Tasks
         {
             if (!cancellationToken.IsCancellationRequested)
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.cancellationToken);
-            return new Task<TResult>(true, default, TaskCreationOptions.None, cancellationToken);
+            return new Task<TResult>(true, default!, TaskCreationOptions.None, cancellationToken); // TODO-NULLABLE-GENERIC
         }
 
         /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified exception.</summary>
@@ -5292,7 +5295,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="function"/> parameter was null.
         /// </exception>
-        public static Task Run(Func<Task> function)
+        public static Task Run(Func<Task?> function)
         {
             return Run(function, default);
         }
@@ -5311,7 +5314,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">
         /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
         /// </exception>
-        public static Task Run(Func<Task> function, CancellationToken cancellationToken)
+        public static Task Run(Func<Task?> function, CancellationToken cancellationToken)
         {
             // Check arguments
             if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
@@ -5321,7 +5324,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);
+            Task<Task?> task1 = Task<Task?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             // 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.
@@ -5340,7 +5343,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="function"/> parameter was null.
         /// </exception>
-        public static Task<TResult> Run<TResult>(Func<Task<TResult>> function)
+        public static Task<TResult> Run<TResult>(Func<Task<TResult>?> function)
         {
             return Run(function, default);
         }
@@ -5356,7 +5359,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="function"/> parameter was null.
         /// </exception>
-        public static Task<TResult> Run<TResult>(Func<Task<TResult>> function, CancellationToken cancellationToken)
+        public static Task<TResult> Run<TResult>(Func<Task<TResult>?> function, CancellationToken cancellationToken)
         {
             // Check arguments
             if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
@@ -5366,7 +5369,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);
+            Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
 
             // 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.
@@ -5475,7 +5478,7 @@ namespace System.Threading.Tasks
         /// <summary>Task that also stores the completion closure and logic for Task.Delay implementation.</summary>
         private class DelayPromise : Task
         {
-            private readonly TimerQueueTimer _timer;
+            private readonly TimerQueueTimer? _timer;
 
             internal DelayPromise(int millisecondsDelay)
             {
@@ -5489,7 +5492,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);
+                    _timer = new TimerQueueTimer(state => ((DelayPromise)state!).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                     if (IsCanceled)
                     {
                         // Handle rare race condition where cancellation occurs prior to our having created and stored the timer, in which case
@@ -5528,7 +5531,7 @@ namespace System.Threading.Tasks
                 Debug.Assert(token.CanBeCanceled);
 
                 _token = token;
-                _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state).CompleteCanceled(), this);
+                _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state!).CompleteCanceled(), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             }
 
             private void CompleteCanceled()
@@ -5593,7 +5596,7 @@ namespace System.Threading.Tasks
                 foreach (var task in tasks)
                 {
                     if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                    taskArray[index++] = task;
+                    taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 }
                 return InternalWhenAll(taskArray);
             }
@@ -5601,10 +5604,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)
+            foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                taskList.Add(task);
+                taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             // Delegate the rest to InternalWhenAll()
@@ -5643,7 +5646,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;
+            int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             if (taskCount == 0) return InternalWhenAll(tasks); // Small optimization in the case of an empty array.
 
             Task[] tasksCopy = new Task[taskCount];
@@ -5651,7 +5654,7 @@ namespace System.Threading.Tasks
             {
                 Task task = tasks[i];
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                tasksCopy[i] = task;
+                tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             // The rest can be delegated to InternalWhenAll()
@@ -5686,7 +5689,7 @@ namespace System.Threading.Tasks
             /// Stores all of the constituent tasks.  Tasks clear themselves out of this
             /// array as they complete, but only if they don't have their wait notification bit set.
             /// </summary>
-            private readonly Task[] m_tasks;
+            private readonly Task?[] m_tasks;
             /// <summary>The number of tasks remaining to complete.</summary>
             private int m_count;
 
@@ -5720,8 +5723,8 @@ namespace System.Threading.Tasks
                 if (Interlocked.Decrement(ref m_count) == 0)
                 {
                     // Set up some accounting variables
-                    List<ExceptionDispatchInfo> observedExceptions = null;
-                    Task canceledTask = null;
+                    List<ExceptionDispatchInfo>? observedExceptions = null;
+                    Task? canceledTask = null;
 
                     // Loop through antecedents:
                     //   If any one of them faults, the result will be faulted
@@ -5837,7 +5840,7 @@ namespace System.Threading.Tasks
                 foreach (var task in tasks)
                 {
                     if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                    taskArray[index++] = task;
+                    taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
                 }
                 return InternalWhenAll<TResult>(taskArray);
             }
@@ -5845,10 +5848,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)
+            foreach (Task<TResult> task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                taskList.Add(task);
+                taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             // Delegate the rest to InternalWhenAll<TResult>().
@@ -5890,7 +5893,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;
+            int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             if (taskCount == 0) return InternalWhenAll<TResult>(tasks); // small optimization in the case of an empty task array
 
             Task<TResult>[] tasksCopy = new Task<TResult>[taskCount];
@@ -5898,7 +5901,7 @@ namespace System.Threading.Tasks
             {
                 Task<TResult> task = tasks[i];
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                tasksCopy[i] = task;
+                tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             // Delegate the rest to InternalWhenAll<TResult>()
@@ -5925,7 +5928,7 @@ namespace System.Threading.Tasks
             /// Stores all of the constituent tasks.  Tasks clear themselves out of this
             /// array as they complete, but only if they don't have their wait notification bit set.
             /// </summary>
-            private readonly Task<T>[] m_tasks;
+            private readonly Task<T>?[] m_tasks;
             /// <summary>The number of tasks remaining to complete.</summary>
             private int m_count;
 
@@ -5961,8 +5964,8 @@ namespace System.Threading.Tasks
                 {
                     // Set up some accounting variables
                     T[] results = new T[m_tasks.Length];
-                    List<ExceptionDispatchInfo> observedExceptions = null;
-                    Task canceledTask = null;
+                    List<ExceptionDispatchInfo>? observedExceptions = null;
+                    Task? canceledTask = null;
 
                     // Loop through antecedents:
                     //   If any one of them faults, the result will be faulted
@@ -5970,7 +5973,7 @@ namespace System.Threading.Tasks
                     //   If none fault or are canceled, then result will be RanToCompletion
                     for (int i = 0; i < m_tasks.Length; i++)
                     {
-                        Task<T> task = m_tasks[i];
+                        Task<T>? task = m_tasks[i];
                         Debug.Assert(task != null, "Constituent task in WhenAll should never be null");
 
                         if (task.IsFaulted)
@@ -6057,7 +6060,7 @@ namespace System.Threading.Tasks
         public static Task<Task> WhenAny(params Task[] tasks)
         {
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
-            if (tasks.Length == 0)
+            if (tasks!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
             }
@@ -6070,7 +6073,7 @@ namespace System.Threading.Tasks
             {
                 Task task = tasks[i];
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                tasksCopy[i] = task;
+                tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             // Previously implemented CommonCWAnyLogic() can handle the rest
@@ -6099,10 +6102,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)
+            foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                taskList.Add(task);
+                taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             if (taskList.Count == 0)
@@ -6183,7 +6186,7 @@ namespace System.Threading.Tasks
 #if PROJECTN
         [DependencyReductionRoot]
 #endif
-        internal virtual Delegate[] GetDelegateContinuationsForDebugger()
+        internal virtual Delegate[]? GetDelegateContinuationsForDebugger()
         {
             //Avoid an infinite loop by making sure the continuation object is not a reference to istelf.
             if (m_continuationObject != this)
@@ -6192,7 +6195,7 @@ namespace System.Threading.Tasks
                 return null;
         }
 
-        private static Delegate[] GetDelegatesFromContinuationObject(object continuationObject)
+        private static Delegate[]? GetDelegatesFromContinuationObject(object? continuationObject)
         {
             if (continuationObject != null)
             {
@@ -6209,7 +6212,7 @@ namespace System.Threading.Tasks
                 if (continuationObject is Task continuationTask)
                 {
                     Debug.Assert(continuationTask.m_action == null);
-                    Delegate[] delegates = continuationTask.GetDelegateContinuationsForDebugger();
+                    Delegate[]? delegates = continuationTask.GetDelegateContinuationsForDebugger();
                     if (delegates != null)
                         return delegates;
                 }
@@ -6221,10 +6224,10 @@ namespace System.Threading.Tasks
                     return new Delegate[] { new Action<Task>(singleCompletionAction.Invoke) };
                 }
 
-                if (continuationObject is List<object> continuationList)
+                if (continuationObject is List<object?> continuationList)
                 {
                     List<Delegate> result = new List<Delegate>();
-                    foreach (object obj in continuationList)
+                    foreach (object? obj in continuationList)
                     {
                         var innerDelegates = GetDelegatesFromContinuationObject(obj);
                         if (innerDelegates != null)
@@ -6248,10 +6251,10 @@ namespace System.Threading.Tasks
         [DependencyReductionRoot]
 #endif
         //Do not remove: VS debugger calls this API directly using func-eval to populate data in the tasks window
-        private static Task GetActiveTaskFromId(int taskId)
+        private static Task? GetActiveTaskFromId(int taskId)
         {
-            Task task = null;
-            s_currentActiveTasks.TryGetValue(taskId, out task);
+            Task? task = null;
+            s_currentActiveTasks?.TryGetValue(taskId, out task);
             return task;
         }
     }
@@ -6283,9 +6286,9 @@ namespace System.Threading.Tasks
             m_task = task;
         }
 
-        public object AsyncState { get { return m_task.AsyncState; } }
+        public object? AsyncState { get { return m_task.AsyncState; } }
         public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
-        public Exception Exception { get { return m_task.Exception; } }
+        public Exception? Exception { get { return m_task.Exception; } }
         public int Id { get { return m_task.Id; } }
         public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
         public TaskStatus Status { get { return m_task.Status; } }
@@ -6519,7 +6522,7 @@ namespace System.Threading.Tasks
         private readonly bool _lookForOce;
 
         public UnwrapPromise(Task outerTask, bool lookForOce)
-            : base((object)null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent)
+            : base((object?)null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent)
         {
             Debug.Assert(outerTask != null, "Expected non-null outerTask");
             _lookForOce = lookForOce;
@@ -6594,7 +6597,7 @@ namespace System.Threading.Tasks
             ThreadPool.UnsafeQueueUserWorkItem(state =>
             {
                 // InvokeCore(completingTask);
-                var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state;
+                var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 tuple.Item1.InvokeCore(tuple.Item2);
             }, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask));
         }
@@ -6648,7 +6651,7 @@ namespace System.Threading.Tasks
                 case TaskStatus.Faulted:
                     var edis = task.GetExceptionDispatchInfos();
                     ExceptionDispatchInfo oceEdi;
-                    OperationCanceledException oce;
+                    OperationCanceledException? oce;
                     if (lookForOce && edis.Count > 0 &&
                         (oceEdi = edis[0]) != null &&
                         (oce = oceEdi.SourceException as OperationCanceledException) != null)
@@ -6670,7 +6673,7 @@ namespace System.Threading.Tasks
                     if (Task.s_asyncDebuggingEnabled)
                         RemoveFromActiveTasks(this);
 
-                    result = TrySetResult(taskTResult != null ? taskTResult.Result : default);
+                    result = TrySetResult(taskTResult != null ? taskTResult.Result : default!); // TODO-NULLABLE-GENERIC
                     break;
             }
             return result;
@@ -6681,7 +6684,7 @@ namespace System.Threading.Tasks
         /// transferring the appropriate results to ourself.
         /// </summary>
         /// <param name="task">The inner task returned by the task provided by the user.</param>
-        private void ProcessInnerTask(Task task)
+        private void ProcessInnerTask(Task? task)
         {
             // If the inner task is null, the proxy should be canceled.
             if (task == null)
index c3ee31a..5147f11 100644 (file)
@@ -10,8 +10,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
-using System;
-using System.Runtime.InteropServices;
+#nullable enable
 using System.Runtime.Serialization;
 
 namespace System.Threading.Tasks
@@ -24,7 +23,7 @@ namespace System.Threading.Tasks
     public class TaskCanceledException : OperationCanceledException
     {
         [NonSerialized]
-        private readonly Task _canceledTask; // The task which has been canceled.
+        private readonly Task? _canceledTask; // The task which has been canceled.
 
         /// <summary>
         /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/> class.
@@ -38,7 +37,7 @@ namespace System.Threading.Tasks
         /// class with a specified error message.
         /// </summary>
         /// <param name="message">The error message that explains the reason for the exception.</param>
-        public TaskCanceledException(string message) : base(message)
+        public TaskCanceledException(string? message) : base(message)
         {
         }
 
@@ -49,7 +48,7 @@ namespace System.Threading.Tasks
         /// </summary>
         /// <param name="message">The error message that explains the reason for the exception.</param>
         /// <param name="innerException">The exception that is the cause of the current exception.</param>
-        public TaskCanceledException(string message, Exception innerException) : base(message, innerException)
+        public TaskCanceledException(string? message, Exception? innerException) : base(message, innerException)
         {
         }
 
@@ -61,7 +60,7 @@ namespace System.Threading.Tasks
         /// <param name="message">The error message that explains the reason for the exception.</param>
         /// <param name="innerException">The exception that is the cause of the current exception.</param>
         /// <param name="token">The <see cref="CancellationToken"/> that triggered the cancellation.</param>
-        public TaskCanceledException(string message, Exception innerException, CancellationToken token) : base(message, innerException, token)
+        public TaskCanceledException(string? message, Exception? innerException, CancellationToken token) : base(message, innerException, token)
         {
         }
 
@@ -70,7 +69,7 @@ namespace System.Threading.Tasks
         /// with a reference to the <see cref="T:System.Threading.Tasks.Task"/> that has been canceled.
         /// </summary>
         /// <param name="task">A task that has been canceled.</param>
-        public TaskCanceledException(Task task) :
+        public TaskCanceledException(Task? task) :
             base(SR.TaskCanceledException_ctor_DefaultMessage, task != null ? task.CancellationToken : new CancellationToken())
         {
             _canceledTask = task;
@@ -94,6 +93,6 @@ namespace System.Threading.Tasks
         /// <see cref="T:System.Threading.Tasks.TaskCanceledException"/>, in which case
         /// this property will return null.
         /// </remarks>
-        public Task Task => _canceledTask;
+        public Task? Task => _canceledTask;
     }
 }
index c85a44f..045486a 100644 (file)
@@ -11,6 +11,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System;
 using System.Diagnostics;
 using System.Collections.Generic;
@@ -81,7 +82,7 @@ namespace System.Threading.Tasks
         /// </summary>
         /// <param name="state">The state to use as the underlying 
         /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>'s AsyncState.</param>
-        public TaskCompletionSource(object state)
+        public TaskCompletionSource(object? state)
             : this(state, TaskCreationOptions.None)
         {
         }
@@ -98,7 +99,7 @@ namespace System.Threading.Tasks
         /// The <paramref name="creationOptions"/> represent options invalid for use
         /// with a <see cref="TaskCompletionSource{TResult}"/>.
         /// </exception>
-        public TaskCompletionSource(object state, TaskCreationOptions creationOptions)
+        public TaskCompletionSource(object? state, TaskCreationOptions creationOptions)
         {
             _task = new Task<TResult>(state, creationOptions);
         }
@@ -150,7 +151,7 @@ namespace System.Threading.Tasks
         {
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
-            bool rval = _task.TrySetException(exception);
+            bool rval = _task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             if (!rval && !_task.IsCompleted) SpinUntilCompleted();
             return rval;
         }
@@ -180,11 +181,11 @@ namespace System.Threading.Tasks
             if (exceptions == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exceptions);
 
             List<Exception> defensiveCopy = new List<Exception>();
-            foreach (Exception e in exceptions)
+            foreach (Exception e in exceptions!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 if (e == null)
                     ThrowHelper.ThrowArgumentException(ExceptionResource.TaskCompletionSourceT_TrySetException_NullException, ExceptionArgument.exceptions);
-                defensiveCopy.Add(e);
+                defensiveCopy.Add(e!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             }
 
             if (defensiveCopy.Count == 0)
@@ -216,7 +217,7 @@ namespace System.Threading.Tasks
         {
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
-            if (!TrySetException(exception))
+            if (!TrySetException(exception!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             {
                 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
             }
index 63ae2bd..0968a74 100644 (file)
@@ -2,9 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System.Security;
+#nullable enable
 using System.Diagnostics;
-using System.Runtime.ExceptionServices;
 using System.Runtime.CompilerServices;
 
 namespace System.Threading.Tasks
@@ -12,13 +11,13 @@ namespace System.Threading.Tasks
     // Task type used to implement: Task ContinueWith(Action<Task,...>)
     internal sealed class ContinuationTaskFromTask : Task
     {
-        private Task m_antecedent;
+        private Task? m_antecedent;
 
         public ContinuationTaskFromTask(
-            Task antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+            Task antecedent, Delegate action, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
             base(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
         {
-            Debug.Assert(action is Action<Task> || action is Action<Task, object>,
+            Debug.Assert(action is Action<Task> || action is Action<Task, object?>,
                 "Invalid delegate type in ContinuationTaskFromTask");
             m_antecedent = antecedent;
         }
@@ -30,7 +29,7 @@ namespace System.Threading.Tasks
         {
             // Get and null out the antecedent.  This is crucial to avoid a memory
             // leak with long chains of continuations.
-            var antecedent = m_antecedent;
+            Task? antecedent = m_antecedent;
             Debug.Assert(antecedent != null,
                 "No antecedent was set for the ContinuationTaskFromTask.");
             m_antecedent = null;
@@ -46,7 +45,7 @@ namespace System.Threading.Tasks
                 return;
             }
 
-            if (m_action is Action<Task, object> actionWithState)
+            if (m_action is Action<Task, object?> actionWithState)
             {
                 actionWithState(antecedent, m_stateObject);
                 return;
@@ -58,13 +57,13 @@ namespace System.Threading.Tasks
     // Task type used to implement: Task<TResult> ContinueWith(Func<Task,...>)
     internal sealed class ContinuationResultTaskFromTask<TResult> : Task<TResult>
     {
-        private Task m_antecedent;
+        private Task? m_antecedent;
 
         public ContinuationResultTaskFromTask(
-            Task antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+            Task antecedent, Delegate function, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
             base(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
         {
-            Debug.Assert(function is Func<Task, TResult> || function is Func<Task, object, TResult>,
+            Debug.Assert(function is Func<Task, TResult> || function is Func<Task, object?, TResult>,
                 "Invalid delegate type in ContinuationResultTaskFromTask");
             m_antecedent = antecedent;
         }
@@ -76,7 +75,7 @@ namespace System.Threading.Tasks
         {
             // Get and null out the antecedent.  This is crucial to avoid a memory
             // leak with long chains of continuations.
-            var antecedent = m_antecedent;
+            Task? antecedent = m_antecedent;
             Debug.Assert(antecedent != null,
                 "No antecedent was set for the ContinuationResultTaskFromTask.");
             m_antecedent = null;
@@ -92,7 +91,7 @@ namespace System.Threading.Tasks
                 return;
             }
 
-            if (m_action is Func<Task, object, TResult> funcWithState)
+            if (m_action is Func<Task, object?, TResult> funcWithState)
             {
                 m_result = funcWithState(antecedent, m_stateObject);
                 return;
@@ -104,13 +103,13 @@ namespace System.Threading.Tasks
     // Task type used to implement: Task ContinueWith(Action<Task<TAntecedentResult>,...>)
     internal sealed class ContinuationTaskFromResultTask<TAntecedentResult> : Task
     {
-        private Task<TAntecedentResult> m_antecedent;
+        private Task<TAntecedentResult>? m_antecedent;
 
         public ContinuationTaskFromResultTask(
-            Task<TAntecedentResult> antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+            Task<TAntecedentResult> antecedent, Delegate action, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
             base(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
         {
-            Debug.Assert(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object>,
+            Debug.Assert(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object?>,
                 "Invalid delegate type in ContinuationTaskFromResultTask");
             m_antecedent = antecedent;
         }
@@ -122,7 +121,7 @@ namespace System.Threading.Tasks
         {
             // Get and null out the antecedent.  This is crucial to avoid a memory
             // leak with long chains of continuations.
-            var antecedent = m_antecedent;
+            Task<TAntecedentResult>? antecedent = m_antecedent;
             Debug.Assert(antecedent != null,
                 "No antecedent was set for the ContinuationTaskFromResultTask.");
             m_antecedent = null;
@@ -138,7 +137,7 @@ namespace System.Threading.Tasks
                 return;
             }
 
-            if (m_action is Action<Task<TAntecedentResult>, object> actionWithState)
+            if (m_action is Action<Task<TAntecedentResult>, object?> actionWithState)
             {
                 actionWithState(antecedent, m_stateObject);
                 return;
@@ -150,13 +149,13 @@ namespace System.Threading.Tasks
     // Task type used to implement: Task<TResult> ContinueWith(Func<Task<TAntecedentResult>,...>)
     internal sealed class ContinuationResultTaskFromResultTask<TAntecedentResult, TResult> : Task<TResult>
     {
-        private Task<TAntecedentResult> m_antecedent;
+        private Task<TAntecedentResult>? m_antecedent;
 
         public ContinuationResultTaskFromResultTask(
-            Task<TAntecedentResult> antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+            Task<TAntecedentResult> antecedent, Delegate function, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
             base(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
         {
-            Debug.Assert(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object, TResult>,
+            Debug.Assert(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object?, TResult>,
                 "Invalid delegate type in ContinuationResultTaskFromResultTask");
             m_antecedent = antecedent;
         }
@@ -168,7 +167,7 @@ namespace System.Threading.Tasks
         {
             // Get and null out the antecedent.  This is crucial to avoid a memory
             // leak with long chains of continuations.
-            var antecedent = m_antecedent;
+            Task<TAntecedentResult>? antecedent = m_antecedent;
             Debug.Assert(antecedent != null,
                 "No antecedent was set for the ContinuationResultTaskFromResultTask.");
             m_antecedent = null;
@@ -184,7 +183,7 @@ namespace System.Threading.Tasks
                 return;
             }
 
-            if (m_action is Func<Task<TAntecedentResult>, object, TResult> funcWithState)
+            if (m_action is Func<Task<TAntecedentResult>, object?, TResult> funcWithState)
             {
                 m_result = funcWithState(antecedent, m_stateObject);
                 return;
@@ -283,7 +282,7 @@ namespace System.Threading.Tasks
             m_options = options;
             m_taskScheduler = scheduler;
             if (AsyncCausalityTracer.LoggingOn)
-                AsyncCausalityTracer.TraceOperationCreation(m_task, "Task.ContinueWith: " + task.m_action.Method.Name);
+                AsyncCausalityTracer.TraceOperationCreation(m_task, "Task.ContinueWith: " + task.m_action!.Method.Name);
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(m_task);
@@ -343,7 +342,7 @@ namespace System.Threading.Tasks
             else continuationTask.InternalCancel(false);
         }
 
-        internal override Delegate[] GetDelegateContinuationsForDebugger()
+        internal override Delegate[]? GetDelegateContinuationsForDebugger()
         {
             if (m_task.m_action == null)
             {
@@ -358,9 +357,13 @@ namespace System.Threading.Tasks
     internal sealed class SynchronizationContextAwaitTaskContinuation : AwaitTaskContinuation
     {
         /// <summary>SendOrPostCallback delegate to invoke the action.</summary>
-        private static readonly SendOrPostCallback s_postCallback = state => ((Action)state)(); // can't use InvokeAction as it's SecurityCritical
+        private static readonly SendOrPostCallback s_postCallback = state =>
+        {
+            Debug.Assert(state is Action);
+            ((Action)state)();
+        };
         /// <summary>Cached delegate for PostAction</summary>
-        private static ContextCallback s_postActionCallback;
+        private static ContextCallback? s_postActionCallback;
         /// <summary>The context with which to run the action.</summary>
         private readonly SynchronizationContext m_syncContext;
 
@@ -403,8 +406,9 @@ namespace System.Threading.Tasks
 
         /// <summary>Calls InvokeOrPostAction(false) on the supplied SynchronizationContextAwaitTaskContinuation.</summary>
         /// <param name="state">The SynchronizationContextAwaitTaskContinuation.</param>
-        private static void PostAction(object state)
+        private static void PostAction(object? state)
         {
+            Debug.Assert(state is SynchronizationContextAwaitTaskContinuation);
             var c = (SynchronizationContextAwaitTaskContinuation)state;
 
             TplEventSource log = TplEventSource.Log;
@@ -438,7 +442,7 @@ namespace System.Threading.Tasks
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static ContextCallback GetPostActionCallback()
         {
-            ContextCallback callback = s_postActionCallback;
+            ContextCallback? callback = s_postActionCallback;
             if (callback == null) { s_postActionCallback = callback = PostAction; } // lazily initialize SecurityCritical delegate
             return callback;
         }
@@ -489,7 +493,7 @@ namespace System.Threading.Tasks
                 {
                     try
                     {
-                        ((Action)state)();
+                        ((Action)state!)(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                     }
                     catch (Exception exception)
                     {
@@ -515,7 +519,7 @@ namespace System.Threading.Tasks
     internal class AwaitTaskContinuation : TaskContinuation, IThreadPoolWorkItem
     {
         /// <summary>The ExecutionContext with which to run the continuation.</summary>
-        private readonly ExecutionContext m_capturedContext;
+        private readonly ExecutionContext? m_capturedContext;
         /// <summary>The action to invoke.</summary>
         protected readonly Action m_action;
 
@@ -539,7 +543,7 @@ namespace System.Threading.Tasks
         /// <param name="state">The state to pass to the action. Must not be null.</param>
         /// <param name="scheduler">The scheduler to target.</param>
         /// <returns>The created task.</returns>
-        protected Task CreateTask(Action<object> action, object state, TaskScheduler scheduler)
+        protected Task CreateTask(Action<object?> action, object? state, TaskScheduler scheduler)
         {
             Debug.Assert(action != null);
             Debug.Assert(scheduler != null);
@@ -615,7 +619,7 @@ namespace System.Threading.Tasks
         void IThreadPoolWorkItem.Execute()
         {
             var log = TplEventSource.Log;
-            ExecutionContext context = m_capturedContext;
+            ExecutionContext? context = m_capturedContext;
 
             if (!log.IsEnabled() && context == null)
             {
@@ -659,7 +663,11 @@ namespace System.Threading.Tasks
         }
 
         /// <summary>Cached delegate that invokes an Action passed as an object parameter.</summary>
-        private readonly static ContextCallback s_invokeContextCallback = (state) => ((Action)state)();
+        private readonly static ContextCallback s_invokeContextCallback = (state) =>
+        {
+            Debug.Assert(state is Action);
+            ((Action)state)();
+        };
         private readonly static Action<Action> s_invokeAction = (action) => action();
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -669,7 +677,7 @@ namespace System.Threading.Tasks
         /// <param name="callback">The callback to run.</param>
         /// <param name="state">The state to pass to the callback.</param>
         /// <param name="currentTask">A reference to Task.t_currentTask.</param>
-        protected void RunCallback(ContextCallback callback, object state, ref Task currentTask)
+        protected void RunCallback(ContextCallback callback, object? state, ref Task? currentTask)
         {
             Debug.Assert(callback != null);
             Debug.Assert(currentTask == Task.t_currentTask);
@@ -681,7 +689,7 @@ namespace System.Threading.Tasks
             {
                 if (prevCurrentTask != null) currentTask = null;
 
-                ExecutionContext context = m_capturedContext;
+                ExecutionContext? context = m_capturedContext;
                 if (context == null)
                 {
                     // If there's no captured context, just run the callback directly.
@@ -717,8 +725,8 @@ namespace System.Threading.Tasks
         /// </remarks>
         internal static void RunOrScheduleAction(Action action, bool allowInlining)
         {
-            ref Task currentTask = ref Task.t_currentTask;
-            Task prevCurrentTask = currentTask;
+            ref Task? currentTask = ref Task.t_currentTask;
+            Task? prevCurrentTask = currentTask;
 
             // If we're not allowed to run here, schedule the action
             if (!allowInlining || !IsValidLocationForInlining)
@@ -753,8 +761,8 @@ namespace System.Threading.Tasks
             // Same logic as in the RunOrScheduleAction(Action, ...) overload, except invoking
             // box.Invoke instead of action().
 
-            ref Task currentTask = ref Task.t_currentTask;
-            Task prevCurrentTask = currentTask;
+            ref Task? currentTask = ref Task.t_currentTask;
+            Task? prevCurrentTask = currentTask;
 
             // If we're not allowed to run here, schedule the action
             if (!allowInlining || !IsValidLocationForInlining)
@@ -798,7 +806,7 @@ namespace System.Threading.Tasks
         /// <summary>Schedules the action to be executed.  No ExecutionContext work is performed used.</summary>
         /// <param name="action">The action to invoke or queue.</param>
         /// <param name="task">The task scheduling the action.</param>
-        internal static void UnsafeScheduleAction(Action action, Task task)
+        internal static void UnsafeScheduleAction(Action action, Task? task)
         {
             AwaitTaskContinuation atc = new AwaitTaskContinuation(action, flowExecutionContext: false);
 
index 67b4220..d35e6a2 100644 (file)
@@ -10,6 +10,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
@@ -33,9 +34,9 @@ namespace System.Threading.Tasks
         /// The lazily-initialized list of faulting exceptions.  Volatile
         /// so that it may be read to determine whether any exceptions were stored.
         /// </summary>
-        private volatile List<ExceptionDispatchInfo> m_faultExceptions;
+        private volatile List<ExceptionDispatchInfo>? m_faultExceptions;
         /// <summary>An exception that triggered the task to cancel.</summary>
-        private ExceptionDispatchInfo m_cancellationException;
+        private ExceptionDispatchInfo? m_cancellationException;
         /// <summary>Whether the holder was "observed" and thus doesn't cause finalization behavior.</summary>
         private volatile bool m_isHandled;
 
@@ -252,7 +253,7 @@ namespace System.Threading.Tasks
         /// <param name="calledFromFinalizer">Whether this is being called from a finalizer.</param>
         /// <param name="includeThisException">An extra exception to be included (optionally).</param>
         /// <returns>The aggregate exception to throw.</returns>
-        internal AggregateException CreateExceptionObject(bool calledFromFinalizer, Exception includeThisException)
+        internal AggregateException CreateExceptionObject(bool calledFromFinalizer, Exception? includeThisException)
         {
             var exceptions = m_faultExceptions;
             Debug.Assert(exceptions != null, "Expected an initialized list.");
@@ -284,7 +285,7 @@ namespace System.Threading.Tasks
         /// </summary>
         internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
         {
-            var exceptions = m_faultExceptions;
+            List<ExceptionDispatchInfo>? exceptions = m_faultExceptions;
             Debug.Assert(exceptions != null, "Expected an initialized list.");
             Debug.Assert(exceptions.Count > 0, "Expected at least one exception.");
             MarkAsHandled(false);
@@ -298,7 +299,7 @@ namespace System.Threading.Tasks
         /// <returns>
         /// The ExceptionDispatchInfo for the cancellation exception.  May be null.
         /// </returns>
-        internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
+        internal ExceptionDispatchInfo? GetCancellationExceptionDispatchInfo()
         {
             var edi = m_cancellationException;
             Debug.Assert(edi == null || edi.SourceException is OperationCanceledException,
index 75b4b0a..4b45f75 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 
index f7816d6..cc5a5a1 100644 (file)
@@ -12,6 +12,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System;
 using System.Collections.Generic;
 using System.Security;
@@ -40,18 +41,18 @@ namespace System.Threading.Tasks
     {
         // member variables
         private readonly CancellationToken m_defaultCancellationToken;
-        private readonly TaskScheduler m_defaultScheduler;
+        private readonly TaskScheduler? m_defaultScheduler;
         private readonly TaskCreationOptions m_defaultCreationOptions;
         private readonly TaskContinuationOptions m_defaultContinuationOptions;
 
         private TaskScheduler DefaultScheduler => m_defaultScheduler ?? TaskScheduler.Current;
 
         // sister method to above property -- avoids a TLS lookup
-        private TaskScheduler GetDefaultScheduler(Task currTask)
+        private TaskScheduler GetDefaultScheduler(Task? currTask)
         {
             return
                 m_defaultScheduler ??
-                (currTask != null && (currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0 ? currTask.ExecutingTaskScheduler :
+                (currTask != null && (currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0 ? currTask.ExecutingTaskScheduler! : // a "current" task must be executing, which means it must have a scheduler
                  TaskScheduler.Default);
         }
 
@@ -119,7 +120,7 @@ namespace System.Threading.Tasks
         /// initialized to the current scheduler (see <see
         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
         /// </remarks>
-        public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
+        public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler.Current
             : this(default, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
         {
         }
@@ -190,7 +191,7 @@ namespace System.Threading.Tasks
         /// current scheduler (see <see
         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
         /// </remarks>
-        public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+        public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler? scheduler)
         {
             CheckMultiTaskContinuationOptions(continuationOptions);
             CheckCreationOptions(creationOptions);
@@ -239,7 +240,7 @@ namespace System.Threading.Tasks
         /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see> 
         /// will be used.
         /// </remarks>
-        public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
+        public TaskScheduler? Scheduler { get { return m_defaultScheduler; } }
 
         /// <summary>
         /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
@@ -281,7 +282,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task StartNew(Action action)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask),
                 m_defaultCreationOptions, InternalTaskOptions.None);
         }
@@ -306,7 +307,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task StartNew(Action action, CancellationToken cancellationToken)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, null, cancellationToken, GetDefaultScheduler(currTask),
                 m_defaultCreationOptions, InternalTaskOptions.None);
         }
@@ -334,7 +335,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task StartNew(Action action, TaskCreationOptions creationOptions)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask), creationOptions,
                 InternalTaskOptions.None);
         }
@@ -396,9 +397,9 @@ 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)
+        public Task StartNew(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
                 m_defaultCreationOptions, InternalTaskOptions.None);
         }
@@ -425,9 +426,9 @@ 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)
+        public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask),
                 m_defaultCreationOptions, InternalTaskOptions.None);
         }
@@ -455,9 +456,9 @@ 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)
+        public Task StartNew(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
                 creationOptions, InternalTaskOptions.None);
         }
@@ -496,7 +497,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,
+        public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                             TaskCreationOptions creationOptions, TaskScheduler scheduler)
         {
             return Task.InternalStartNew(
@@ -525,7 +526,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> StartNew<TResult>(Func<TResult> function)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -556,7 +557,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, cancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -588,7 +589,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> StartNew<TResult>(Func<TResult> function, TaskCreationOptions creationOptions)
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
                 creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -657,9 +658,9 @@ 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)
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -690,9 +691,9 @@ 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)
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -724,9 +725,9 @@ 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)
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
-            Task currTask = Task.InternalCurrent;
+            Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
                 creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
         }
@@ -769,7 +770,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,
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             TaskCreationOptions creationOptions, TaskScheduler scheduler)
         {
             return Task<TResult>.StartNew(
@@ -879,9 +880,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync(
-            Func<AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
-            object state)
+            object? state)
         {
             return FromAsync(beginMethod, endMethod, state, m_defaultCreationOptions);
         }
@@ -909,8 +910,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync(
-            Func<AsyncCallback, object, IAsyncResult> beginMethod,
-            Action<IAsyncResult> endMethod, object state, TaskCreationOptions creationOptions)
+            Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+            Action<IAsyncResult> endMethod, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, state, creationOptions);
         }
@@ -938,10 +939,10 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync<TArg1>(
-            Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
             TArg1 arg1,
-            object state)
+            object? state)
         {
             return FromAsync(beginMethod, endMethod, arg1, state, m_defaultCreationOptions);
         }
@@ -974,9 +975,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync<TArg1>(
-            Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
-            TArg1 arg1, object state, TaskCreationOptions creationOptions)
+            TArg1 arg1, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, state, creationOptions);
         }
@@ -1008,9 +1009,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync<TArg1, TArg2>(
-            Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
-            TArg1 arg1, TArg2 arg2, object state)
+            TArg1 arg1, TArg2 arg2, object? state)
         {
             return FromAsync(beginMethod, endMethod, arg1, arg2, state, m_defaultCreationOptions);
         }
@@ -1047,9 +1048,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync<TArg1, TArg2>(
-            Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
-            TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+            TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, arg2, state, creationOptions);
         }
@@ -1085,9 +1086,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync<TArg1, TArg2, TArg3>(
-            Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
-            TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+            TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state)
         {
             return FromAsync(beginMethod, endMethod, arg1, arg2, arg3, state, m_defaultCreationOptions);
         }
@@ -1128,9 +1129,9 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task FromAsync<TArg1, TArg2, TArg3>(
-            Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+            Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
             Action<IAsyncResult> endMethod,
-            TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+            TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<VoidTaskResult>.FromAsyncImpl<TArg1, TArg2, TArg3>(beginMethod, null, endMethod, arg1, arg2, arg3, state, creationOptions);
         }
@@ -1243,8 +1244,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TResult>(
-            Func<AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, object state)
+            Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, object? state)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
         }
@@ -1275,8 +1276,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TResult>(
-            Func<AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
+            Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
         }
@@ -1306,8 +1307,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TResult>(
-            Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state)
+            Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object? state)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
         }
@@ -1341,8 +1342,8 @@ namespace System.Threading.Tasks
         /// <remarks>
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
-        public Task<TResult> FromAsync<TArg1, TResult>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state, TaskCreationOptions creationOptions)
+        public Task<TResult> FromAsync<TArg1, TResult>(Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
         }
@@ -1375,8 +1376,8 @@ namespace System.Threading.Tasks
         /// <remarks>
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
-        public Task<TResult> FromAsync<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state)
+        public Task<TResult> FromAsync<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object? state)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
         }
@@ -1415,8 +1416,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2, TResult>(
-            Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+            Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
         }
@@ -1454,8 +1455,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(
-            Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+            Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
         }
@@ -1498,8 +1499,8 @@ namespace System.Threading.Tasks
         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
         /// </remarks>
         public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(
-            Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+            Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
+            Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
         {
             return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
         }
@@ -2284,7 +2285,7 @@ namespace System.Threading.Tasks
             private const int CompletedFlag = 0b_01;
             private const int SyncBlockingFlag = 0b_10;
 
-            private IList<Task> _tasks; // must track this for cleanup
+            private IList<Task>? _tasks; // must track this for cleanup
             private int _stateFlags;
 
             public CompleteOnInvokePromise(IList<Task> tasks, bool isSyncBlocking) : base()
@@ -2331,7 +2332,8 @@ namespace System.Threading.Tasks
                     // This may also help to avoided unnecessary invocations of this whenComplete delegate.
                     // Note that we may be attempting to remove a continuation from a task that hasn't had it
                     // added yet; while there's overhead there, the operation won't hurt anything.
-                    var tasks = _tasks;
+                    IList<Task>? tasks = _tasks;
+                    Debug.Assert(tasks != null, "Should not have been nulled out yet.");
                     int numTasks = tasks.Count;
                     for (int i = 0; i < numTasks; i++)
                     {
@@ -2411,8 +2413,8 @@ namespace System.Threading.Tasks
         internal static void CommonCWAnyLogicCleanup(Task<Task> continuation)
         {
             // Force cleanup of the promise (e.g. removing continuations from each
-            // constituent task), by completing the promise with any value.
-            ((CompleteOnInvokePromise)continuation).Invoke(null);
+            // constituent task), by completing the promise with any value (it's not observable).
+            ((CompleteOnInvokePromise)continuation).Invoke(null!);
         }
 
         /// <summary>
index 1d1a581..d894004 100644 (file)
@@ -10,6 +10,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+#nullable enable
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
@@ -142,7 +143,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.NotSupportedException">
         /// This scheduler is unable to generate a list of queued tasks at this time.
         /// </exception>
-        protected abstract IEnumerable<Task> GetScheduledTasks();
+        protected abstract IEnumerable<Task>? GetScheduledTasks();
 
         /// <summary>
         /// Indicates the maximum concurrency level this 
@@ -174,7 +175,7 @@ namespace System.Threading.Tasks
             // Do not inline unstarted tasks (i.e., task.ExecutingTaskScheduler == null).
             // Do not inline TaskCompletionSource-style (a.k.a. "promise") tasks.
             // No need to attempt inlining if the task body was already run (i.e. either TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bits set)
-            TaskScheduler ets = task.ExecutingTaskScheduler;
+            TaskScheduler? ets = task.ExecutingTaskScheduler;
 
             // Delegate cross-scheduler inlining requests to target scheduler
             if (ets != this && ets != null) return ets.TryRunInline(task, taskWasPreviouslyQueued);
@@ -254,7 +255,7 @@ namespace System.Threading.Tasks
         //
 
         // The global container that keeps track of TaskScheduler instances for debugging purposes.
-        private static ConditionalWeakTable<TaskScheduler, object> s_activeTaskSchedulers;
+        private static ConditionalWeakTable<TaskScheduler, object?>? s_activeTaskSchedulers;
 
         // An AppDomain-wide default manager.
         private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler();
@@ -292,13 +293,13 @@ namespace System.Threading.Tasks
         /// <summary>Adds this scheduler ot the active schedulers tracking collection for debugging purposes.</summary>
         private void AddToActiveTaskSchedulers()
         {
-            ConditionalWeakTable<TaskScheduler, object> activeTaskSchedulers = s_activeTaskSchedulers;
+            ConditionalWeakTable<TaskScheduler, object?>? activeTaskSchedulers = s_activeTaskSchedulers;
             if (activeTaskSchedulers == null)
             {
-                Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object>(), null);
+                Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object?>(), null);
                 activeTaskSchedulers = s_activeTaskSchedulers;
             }
-            activeTaskSchedulers.Add(this, null);
+            activeTaskSchedulers!.Add(this, null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         }
 
         /// <summary>
@@ -323,8 +324,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                TaskScheduler current = InternalCurrent;
-                return current ?? TaskScheduler.Default;
+                return InternalCurrent ?? Default;
             }
         }
 
@@ -335,11 +335,11 @@ namespace System.Threading.Tasks
         /// <remarks>
         /// When not called from within a task, <see cref="InternalCurrent"/> will return null.
         /// </remarks>
-        internal static TaskScheduler InternalCurrent
+        internal static TaskScheduler? InternalCurrent
         {
             get
             {
-                Task currentTask = Task.InternalCurrent;
+                Task? currentTask = Task.InternalCurrent;
                 return ((currentTask != null)
                     && ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
                     ) ? currentTask.ExecutingTaskScheduler : null;
@@ -472,11 +472,11 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.NotSupportedException">
         /// This scheduler is unable to generate a list of queued tasks at this time.
         /// </exception>
-        internal Task[] GetScheduledTasksForDebugger()
+        internal Task[]? GetScheduledTasksForDebugger()
         {
             // this can throw InvalidOperationException indicating that they are unable to provide the info
             // at the moment. We should let the debugger receive that exception so that it can indicate it in the UI
-            IEnumerable<Task> activeTasksSource = GetScheduledTasks();
+            IEnumerable<Task>? activeTasksSource = GetScheduledTasks();
 
             if (activeTasksSource == null)
                 return null;
@@ -553,7 +553,7 @@ namespace System.Threading.Tasks
             }
 
             // returns the scheduler's GetScheduledTasks
-            public IEnumerable<Task> ScheduledTasks
+            public IEnumerable<Task>? ScheduledTasks
             {
                 get { return m_taskScheduler.GetScheduledTasks(); }
             }
@@ -578,15 +578,9 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.InvalidOperationException">This constructor expects <see cref="T:System.Threading.SynchronizationContext.Current"/> to be set.</exception>
         internal SynchronizationContextTaskScheduler()
         {
-            SynchronizationContext synContext = SynchronizationContext.Current;
-
-            // make sure we have a synccontext to work with
-            if (synContext == null)
-            {
+            m_synchronizationContext = SynchronizationContext.Current ??
+                // make sure we have a synccontext to work with
                 throw new InvalidOperationException(SR.TaskScheduler_FromCurrentSynchronizationContext_NoCurrent);
-            }
-
-            m_synchronizationContext = synContext;
         }
 
         /// <summary>
@@ -615,11 +609,12 @@ namespace System.Threading.Tasks
                 return TryExecuteTask(task);
             }
             else
+            {
                 return false;
+            }
         }
 
-        // not implemented
-        protected override IEnumerable<Task> GetScheduledTasks()
+        protected override IEnumerable<Task>? GetScheduledTasks()
         {
             return null;
         }
@@ -640,7 +635,11 @@ namespace System.Threading.Tasks
         }
 
         // preallocated SendOrPostCallback delegate
-        private static readonly SendOrPostCallback s_postCallback = s => ((Task)s).ExecuteEntry(); // with double-execute check because SC could be buggy
+        private static readonly SendOrPostCallback s_postCallback = s =>
+        {
+            Debug.Assert(s is Task);
+            ((Task)s).ExecuteEntry(); // with double-execute check because SC could be buggy
+        };
     }
 
     /// <summary>
@@ -655,7 +654,7 @@ namespace System.Threading.Tasks
     /// </remarks>
     public class UnobservedTaskExceptionEventArgs : EventArgs
     {
-        private AggregateException m_exception;
+        private AggregateException? m_exception;
         internal bool m_observed = false;
 
         /// <summary>
@@ -663,7 +662,7 @@ namespace System.Threading.Tasks
         /// with the unobserved exception.
         /// </summary>
         /// <param name="exception">The Exception that has gone unobserved.</param>
-        public UnobservedTaskExceptionEventArgs(AggregateException exception) { m_exception = exception; }
+        public UnobservedTaskExceptionEventArgs(AggregateException? exception) { m_exception = exception; }
 
         /// <summary>
         /// Marks the <see cref="Exception"/> as "observed," thus preventing it
@@ -679,6 +678,6 @@ namespace System.Threading.Tasks
         /// <summary>
         /// The Exception that went unobserved.
         /// </summary>
-        public AggregateException Exception { get { return m_exception; } }
+        public AggregateException? Exception { get { return m_exception; } }
     }
 }
index 85ec497..c68469c 100644 (file)
@@ -10,8 +10,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
-using System;
-using System.Runtime.InteropServices;
+#nullable enable
 using System.Runtime.Serialization;
 
 namespace System.Threading.Tasks
@@ -36,7 +35,7 @@ namespace System.Threading.Tasks
         /// class with a specified error message.
         /// </summary>
         /// <param name="message">The error message that explains the reason for the exception.</param>
-        public TaskSchedulerException(string message) : base(message)
+        public TaskSchedulerException(string? message) : base(message)
         {
         }
 
@@ -46,7 +45,7 @@ namespace System.Threading.Tasks
         /// this exception.
         /// </summary>
         /// <param name="innerException">The exception that is the cause of the current exception.</param>
-        public TaskSchedulerException(Exception innerException)
+        public TaskSchedulerException(Exception? innerException)
             : base(SR.TaskSchedulerException_ctor_DefaultMessage, innerException)
         {
         }
@@ -58,7 +57,7 @@ namespace System.Threading.Tasks
         /// </summary>
         /// <param name="message">The error message that explains the reason for the exception.</param>
         /// <param name="innerException">The exception that is the cause of the current exception.</param>
-        public TaskSchedulerException(string message, Exception innerException) : base(message, innerException)
+        public TaskSchedulerException(string? message, Exception? innerException) : base(message, innerException)
         {
         }
 
index add41f5..110520a 100644 (file)
@@ -16,6 +16,7 @@
 //         return TaskToApm.End<int>(asyncResult);
 //     }
 
+#nullable enable
 using System.Diagnostics;
 
 namespace System.Threading.Tasks
@@ -33,7 +34,7 @@ namespace System.Threading.Tasks
         /// <param name="callback">The callback to be invoked upon completion.</param>
         /// <param name="state">The state to be stored in the IAsyncResult.</param>
         /// <returns>An IAsyncResult to represent the task's asynchronous operation.</returns>
-        public static IAsyncResult Begin(Task task, AsyncCallback callback, object state)
+        public static IAsyncResult Begin(Task task, AsyncCallback callback, object? state)
         {
             Debug.Assert(task != null);
 
@@ -63,7 +64,7 @@ namespace System.Threading.Tasks
         /// <param name="asyncResult">The IAsyncResult to unwrap.</param>
         public static void End(IAsyncResult asyncResult)
         {
-            Task task;
+            Task? task;
 
             // If the IAsyncResult is our task-wrapping IAsyncResult, extract the Task.
             var twar = asyncResult as TaskWrapperAsyncResult;
@@ -91,7 +92,7 @@ namespace System.Threading.Tasks
         /// <param name="asyncResult">The IAsyncResult to unwrap.</param>
         public static TResult End<TResult>(IAsyncResult asyncResult)
         {
-            Task<TResult> task;
+            Task<TResult>? task;
 
             // If the IAsyncResult is our task-wrapping IAsyncResult, extract the Task.
             var twar = asyncResult as TaskWrapperAsyncResult;
@@ -158,7 +159,7 @@ namespace System.Threading.Tasks
             /// <summary>The wrapped Task.</summary>
             internal readonly Task Task;
             /// <summary>The new AsyncState value.</summary>
-            private readonly object _state;
+            private readonly object? _state;
             /// <summary>The new CompletedSynchronously value.</summary>
             private readonly bool _completedSynchronously;
 
@@ -166,7 +167,7 @@ namespace System.Threading.Tasks
             /// <param name="task">The Task to wrap.</param>
             /// <param name="state">The new AsyncState value</param>
             /// <param name="completedSynchronously">The new CompletedSynchronously value.</param>
-            internal TaskWrapperAsyncResult(Task task, object state, bool completedSynchronously)
+            internal TaskWrapperAsyncResult(Task task, object? state, bool completedSynchronously)
             {
                 Debug.Assert(task != null);
                 Debug.Assert(!completedSynchronously || task.IsCompleted, "If completedSynchronously is true, the task must be completed.");
@@ -180,7 +181,7 @@ namespace System.Threading.Tasks
             // - IsCompleted and AsyncWaitHandle just pass through to the Task.
             // - AsyncState and CompletedSynchronously return the corresponding values stored in this object.
 
-            object IAsyncResult.AsyncState { get { return _state; } }
+            object? IAsyncResult.AsyncState { get { return _state; } }
             bool IAsyncResult.CompletedSynchronously { get { return _completedSynchronously; } }
             bool IAsyncResult.IsCompleted { get { return this.Task.IsCompleted; } }
             WaitHandle IAsyncResult.AsyncWaitHandle { get { return ((IAsyncResult)this.Task).AsyncWaitHandle; } }
index 9ab28ef..05cb75b 100644 (file)
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
-using System;
-using System.Security;
-using System.Diagnostics;
+#nullable enable
 using System.Collections.Generic;
-using System.Text;
+using System.Diagnostics;
 
 namespace System.Threading.Tasks
 {
@@ -33,7 +31,11 @@ namespace System.Threading.Tasks
         }
 
         // static delegate for threads allocated to handle LongRunning tasks.
-        private static readonly ParameterizedThreadStart s_longRunningThreadWork = s => ((Task)s).ExecuteEntryUnsafe(threadPoolThread: null);
+        private static readonly ParameterizedThreadStart s_longRunningThreadWork = s =>
+        {
+            Debug.Assert(s is Task);
+            ((Task)s).ExecuteEntryUnsafe(threadPoolThread: null);
+        };
 
         /// <summary>
         /// Schedules a task to the ThreadPool.
index 94f0ec3..184cc32 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Runtime.CompilerServices;
 using System.Diagnostics.Tracing;
 using Internal.Runtime.CompilerServices;
index e9285ce..1b17561 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
@@ -63,7 +64,7 @@ namespace System.Threading.Tasks
         internal static Task CompletedTask => Task.CompletedTask;
 
         /// <summary>null if representing a successful synchronous completion, otherwise a <see cref="Task"/> or a <see cref="IValueTaskSource"/>.</summary>
-        internal readonly object _obj;
+        internal readonly object? _obj;
         /// <summary>Opaque value passed through to the <see cref="IValueTaskSource"/>.</summary>
         internal readonly short _token;
         /// <summary>true to continue on the capture context; otherwise, true.</summary>
@@ -106,7 +107,7 @@ namespace System.Threading.Tasks
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private ValueTask(object obj, short token, bool continueOnCapturedContext)
+        private ValueTask(object? obj, short token, bool continueOnCapturedContext)
         {
             _obj = obj;
             _token = token;
@@ -117,7 +118,7 @@ namespace System.Threading.Tasks
         public override int GetHashCode() => _obj?.GetHashCode() ?? 0;
 
         /// <summary>Returns a value indicating whether this value is equal to a specified <see cref="object"/>.</summary>
-        public override bool Equals(object obj) =>
+        public override bool Equals(object? obj) =>
             obj is ValueTask &&
             Equals((ValueTask)obj);
 
@@ -141,7 +142,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task AsTask()
         {
-            object obj = _obj;
+            object? obj = _obj;
             Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
             return 
                 obj == null ? CompletedTask :
@@ -200,7 +201,7 @@ namespace System.Threading.Tasks
         /// <summary>Type used to create a <see cref="Task"/> to represent a <see cref="IValueTaskSource"/>.</summary>
         private sealed class ValueTaskSourceAsTask : Task
         {
-            private static readonly Action<object> s_completionAction = state =>
+            private static readonly Action<object?> s_completionAction = state =>
             {
                 if (!(state is ValueTaskSourceAsTask vtst) ||
                     !(vtst._source is IValueTaskSource source))
@@ -240,11 +241,11 @@ namespace System.Threading.Tasks
             };
 
             /// <summary>The associated <see cref="IValueTaskSource"/>.</summary>
-            private IValueTaskSource _source;
+            private IValueTaskSource? _source;
             /// <summary>The token to pass through to operations on <see cref="_source"/></summary>
             private readonly short _token;
 
-            public ValueTaskSourceAsTask(IValueTaskSource source, short token)
+            internal ValueTaskSourceAsTask(IValueTaskSource source, short token)
             {
                 _token = token;
                 _source = source;
@@ -258,7 +259,7 @@ namespace System.Threading.Tasks
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
 
                 if (obj == null)
@@ -281,7 +282,7 @@ namespace System.Threading.Tasks
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
 
                 if (obj == null)
@@ -303,7 +304,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
 
                 if (obj == null)
@@ -330,7 +331,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
 
                 if (obj == null)
@@ -352,7 +353,7 @@ namespace System.Threading.Tasks
         [StackTraceHidden]
         internal void ThrowIfCompletedUnsuccessfully()
         {
-            object obj = _obj;
+            object? obj = _obj;
             Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
 
             if (obj != null)
@@ -411,9 +412,9 @@ namespace System.Threading.Tasks
     public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
     {
         /// <summary>A task canceled using `new CancellationToken(true)`. Lazily created only when first needed.</summary>
-        private static Task<TResult> s_canceledTask;
+        private static Task<TResult>? s_canceledTask;
         /// <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;
+        internal readonly object? _obj;
         /// <summary>The result to be used if the operation completed successfully synchronously.</summary>
         internal readonly TResult _result;
         /// <summary>Opaque value passed through to the <see cref="IValueTaskSource{TResult}"/>.</summary>
@@ -449,7 +450,7 @@ namespace System.Threading.Tasks
 
             _obj = task;
 
-            _result = default;
+            _result = default!; // TODO-NULLABLE-GENERIC
             _continueOnCapturedContext = true;
             _token = 0;
         }
@@ -468,7 +469,7 @@ namespace System.Threading.Tasks
             _obj = source;
             _token = token;
 
-            _result = default;
+            _result = default!; // TODO-NULLABLE-GENERIC
             _continueOnCapturedContext = true;
         }
 
@@ -478,7 +479,7 @@ namespace System.Threading.Tasks
         /// <param name="token">The token.</param>
         /// <param name="continueOnCapturedContext">true to continue on captured context; otherwise, false.</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private ValueTask(object obj, TResult result, short token, bool continueOnCapturedContext)
+        private ValueTask(object? obj, TResult result, short token, bool continueOnCapturedContext)
         {
             _obj = obj;
             _result = result;
@@ -494,7 +495,7 @@ namespace System.Threading.Tasks
             0;
 
         /// <summary>Returns a value indicating whether this value is equal to a specified <see cref="object"/>.</summary>
-        public override bool Equals(object obj) =>
+        public override bool Equals(object? obj) =>
             obj is ValueTask<TResult> &&
             Equals((ValueTask<TResult>)obj);
 
@@ -521,7 +522,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> AsTask()
         {
-            object obj = _obj;
+            object? obj = _obj;
             Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
 
             if (obj == null)
@@ -572,11 +573,11 @@ namespace System.Threading.Tasks
                             return task;
                         }
 
-                        Task<TResult> canceledTask = s_canceledTask;
+                        Task<TResult>? canceledTask = s_canceledTask;
                         if (canceledTask == null)
                         {
                             // Benign race condition to initialize cached task, as identity doesn't matter.
-                            s_canceledTask = Task.FromCanceled<TResult>(new CancellationToken(true));
+                            s_canceledTask = canceledTask = Task.FromCanceled<TResult>(new CancellationToken(true));
                         }
                         return canceledTask;
                     }
@@ -593,7 +594,7 @@ namespace System.Threading.Tasks
         /// <summary>Type used to create a <see cref="Task{TResult}"/> to represent a <see cref="IValueTaskSource{TResult}"/>.</summary>
         private sealed class ValueTaskSourceAsTask : Task<TResult>
         {
-            private static readonly Action<object> s_completionAction = state =>
+            private static readonly Action<object?> s_completionAction = state =>
             {
                 if (!(state is ValueTaskSourceAsTask vtst) ||
                     !(vtst._source is IValueTaskSource<TResult> source))
@@ -632,7 +633,7 @@ namespace System.Threading.Tasks
             };
 
             /// <summary>The associated <see cref="IValueTaskSource"/>.</summary>
-            private IValueTaskSource<TResult> _source;
+            private IValueTaskSource<TResult>? _source;
             /// <summary>The token to pass through to operations on <see cref="_source"/></summary>
             private readonly short _token;
 
@@ -650,7 +651,7 @@ namespace System.Threading.Tasks
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
 
                 if (obj == null)
@@ -673,7 +674,7 @@ namespace System.Threading.Tasks
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
 
                 if (obj == null)
@@ -695,7 +696,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
 
                 if (obj == null)
@@ -722,7 +723,7 @@ namespace System.Threading.Tasks
         {
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
 
                 if (obj == null)
@@ -745,7 +746,7 @@ namespace System.Threading.Tasks
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             {
-                object obj = _obj;
+                object? obj = _obj;
                 Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
 
                 if (obj == null)
@@ -776,7 +777,7 @@ namespace System.Threading.Tasks
             new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, continueOnCapturedContext));
 
         /// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
-        public override string ToString()
+        public override string? ToString()
         {
             if (IsCompletedSuccessfully)
             {
index a212030..66d01ac 100644 (file)
@@ -718,7 +718,7 @@ namespace System.Threading
     {
         private const uint MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe;
 
-        private TimerHolder _timer = null!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+        private TimerHolder _timer = null!; // initialized in helper called by ctors
 
         public Timer(TimerCallback callback,
                      object? state,
index 77dcea5..b281c92 100644 (file)
@@ -20,7 +20,7 @@ namespace System
 
         // MethodBase, either cached after first request or assigned from a DynamicMethod
         // For open delegates to collectible types, this may be a LoaderAllocator object
-        internal object _methodBase = null!; // Initialized by VM as needed
+        internal object? _methodBase; // Initialized by VM as needed
 
         // _methodPtr is a pointer to the method we will invoke
         // It could be a small thunk if this is a static or UM call
index dfb8cea..e128c75 100644 (file)
@@ -578,7 +578,7 @@ namespace System
         {
             if (target == null)
                 ThrowNullThisInDelegateToInstance();
-            this._target = target!; // TODO-NULLABLE: Compiler can't see throw helper above
+            this._target = target!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             this._methodPtr = methodPtr;
         }
 
index d72ca12..4919166 100644 (file)
@@ -2,16 +2,12 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System.Security;
+#nullable enable
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
 using System.Runtime.InteropServices.WindowsRuntime;
-
 using WFD = Windows.Foundation.Diagnostics;
 
-
 namespace System.Threading.Tasks
 {
     internal static class AsyncCausalityTracer
@@ -64,7 +60,7 @@ namespace System.Threading.Tasks
             //COM Interface GUID  {50850B26-267E-451B-A890-AB6A370245EE}
             Guid guid = new Guid(0x50850B26, 0x267E, 0x451B, 0xA8, 0x90, 0XAB, 0x6A, 0x37, 0x02, 0x45, 0xEE);
 
-            object factory = null;
+            object? factory = null;
 
             try
             {
index a09279c..131fffc 100644 (file)
@@ -2,9 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-//
-//
-
+#nullable enable
 using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;