Add and apply nullable attributes (dotnet/coreclr#24679)
authorStephen Toub <stoub@microsoft.com>
Tue, 28 May 2019 10:04:13 +0000 (06:04 -0400)
committerGitHub <noreply@github.com>
Tue, 28 May 2019 10:04:13 +0000 (06:04 -0400)
* Add and apply nullable attributes

* Adapt to API review decisions

* Address PR feedback

Commit migrated from https://github.com/dotnet/coreclr/commit/4a1275434fff99206f2a28f5f0e87f124069eb7f

214 files changed:
src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs
src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/XplatEventLogger.cs
src/coreclr/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ISymWrapperCore.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs
src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs
src/coreclr/src/System.Private.CoreLib/src/System/RtType.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsMethod.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyDependencyResolver.cs
src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs
src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs
src/coreclr/src/System.Private.CoreLib/src/System/Threading/Monitor.cs
src/coreclr/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Utf8String.Construction.cs
src/coreclr/src/System.Private.CoreLib/src/System/Utf8String.cs
src/coreclr/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs
src/libraries/System.Private.CoreLib/src/Internal/Win32/RegistryKey.cs
src/libraries/System.Private.CoreLib/src/Interop/Unix/Interop.Errors.cs
src/libraries/System.Private.CoreLib/src/Interop/Unix/System.Native/Interop.MountPoints.cs
src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.CreateFile.cs
src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.CreateFile2.cs
src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs
src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/AppContext.cs
src/libraries/System.Private.CoreLib/src/System/AppDomain.cs
src/libraries/System.Private.CoreLib/src/System/Array.cs
src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs
src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
src/libraries/System.Private.CoreLib/src/System/CharEnumerator.cs
src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueueSegment.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IComparer.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IDictionary.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEqualityComparer.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyDictionary.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.SerializationInfoTable.cs
src/libraries/System.Private.CoreLib/src/System/Collections/IDictionary.cs
src/libraries/System.Private.CoreLib/src/System/Collections/ListDictionaryInternal.cs
src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/Collection.cs
src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
src/libraries/System.Private.CoreLib/src/System/Convert.cs
src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs
src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs
src/libraries/System.Private.CoreLib/src/System/Delegate.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/DiagnosticCounter.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/ConcurrentSet.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs
src/libraries/System.Private.CoreLib/src/System/Enum.cs
src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs
src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs
src/libraries/System.Private.CoreLib/src/System/Environment.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Unix.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/IdnMapping.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.Win32.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseLunisolarCalendar.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/SortVersion.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/TextElementEnumerator.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanParse.cs
src/libraries/System.Private.CoreLib/src/System/IComparable.cs
src/libraries/System.Private.CoreLib/src/System/IEquatable.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Unix.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileStream.Windows.cs
src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs
src/libraries/System.Private.CoreLib/src/System/IO/Path.cs
src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs
src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs
src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs
src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs
src/libraries/System.Private.CoreLib/src/System/IO/TextReader.cs
src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs
src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryStream.cs
src/libraries/System.Private.CoreLib/src/System/Lazy.cs
src/libraries/System.Private.CoreLib/src/System/Math.cs
src/libraries/System.Private.CoreLib/src/System/Memory.cs
src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.Fast.cs
src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.tt
src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureType.cs
src/libraries/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs
src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs
src/libraries/System.Private.CoreLib/src/System/Resources/ResourceReader.Core.cs
src/libraries/System.Private.CoreLib/src/System/Resources/ResourceReader.cs
src/libraries/System.Private.CoreLib/src/System/Resources/ResourceSet.cs
src/libraries/System.Private.CoreLib/src/System/Resources/RuntimeResourceSet.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/StrongBox.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/ExceptionServices/ExceptionDispatchInfo.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationInfo.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationInfoEnumerator.cs
src/libraries/System.Private.CoreLib/src/System/Span.Fast.cs
src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs
src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs
src/libraries/System.Private.CoreLib/src/System/String.Searching.cs
src/libraries/System.Private.CoreLib/src/System/String.cs
src/libraries/System.Private.CoreLib/src/System/StringComparer.cs
src/libraries/System.Private.CoreLib/src/System/Text/DecoderBestFitFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/DecoderExceptionFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/DecoderFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/DecoderNLS.cs
src/libraries/System.Private.CoreLib/src/System/Text/DecoderReplacementFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/EncoderBestFitFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/EncoderFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/EncoderReplacementFallback.cs
src/libraries/System.Private.CoreLib/src/System/Text/Encoding.cs
src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs
src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs
src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs
src/libraries/System.Private.CoreLib/src/System/Text/StringRuneEnumerator.cs
src/libraries/System.Private.CoreLib/src/System/Text/UTF32Encoding.cs
src/libraries/System.Private.CoreLib/src/System/Text/UTF8Encoding.cs
src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.cs
src/libraries/System.Private.CoreLib/src/System/Text/UnicodeEncoding.cs
src/libraries/System.Private.CoreLib/src/System/Text/ValueStringBuilder.cs
src/libraries/System.Private.CoreLib/src/System/Threading/AsyncLocal.cs
src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs
src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs
src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs
src/libraries/System.Private.CoreLib/src/System/Threading/LazyInitializer.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.cs
src/libraries/System.Private.CoreLib/src/System/Threading/ReaderWriterLockSlim.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Sources/IValueTaskSource.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskCompletionSource.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs
src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Volatile.cs
src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs
src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs
src/libraries/System.Private.CoreLib/src/System/TimeZone.cs
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs
src/libraries/System.Private.CoreLib/src/System/Tuple.cs
src/libraries/System.Private.CoreLib/src/System/Type.Helpers.cs
src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs
src/libraries/System.Private.CoreLib/src/System/Version.cs
src/libraries/System.Private.CoreLib/src/System/WinRTFolderPaths.cs

index 353fa82..1a6a581 100644 (file)
@@ -54,8 +54,8 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-    <!-- Remove CS8608 once https://github.com/dotnet/roslyn/issues/23268 is resolved -->
-    <NoWarn>649,1573,1591,0419,3021,CS8609</NoWarn>
+    <!-- Remove CS8609 once https://github.com/dotnet/roslyn/issues/23268 is resolved -->
+    <NoWarn>$(NoWarn);649,1573,1591,0419,3021,CS8609</NoWarn>
     <Nullable>enable</Nullable>
 
     <!-- Ignore all previous constants since SPCL is sensitive to what is defined and the Sdk adds some by default -->
index ee4a481..14f6847 100644 (file)
@@ -293,7 +293,7 @@ namespace System
         {
             if (indices == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
-            if (Rank != indices!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (Rank != indices!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
 
             TypedReference elemref = new TypedReference();
index 75b9c4b..e17f430 100644 (file)
@@ -294,7 +294,7 @@ namespace System
                 {
                     if (objAttr[i] != null)
                     {
-                        attributes[count] = (Attribute)objAttr[i]!; // TODO-NULLABLE https://github.com/dotnet/roslyn/issues/34644
+                        attributes[count] = (Attribute)objAttr[i]!; // TODO-NULLABLE Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                         count++;
                     }
                 }
index ef0a6ef..40e6790 100644 (file)
@@ -138,7 +138,7 @@ namespace System.Collections.Generic
             {
                 for (int i = startIndex; i < endIndex; i++)
                 {
-                    if (array[i] != null && array[i]!.Equals(value)) return i; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                    if (array[i] != null && array[i]!.Equals(value)) return i; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                 }
             }
             return -1;
@@ -158,7 +158,7 @@ namespace System.Collections.Generic
             {
                 for (int i = startIndex; i >= endIndex; i--)
                 {
-                    if (array[i] != null && array[i]!.Equals(value)) return i; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                    if (array[i] != null && array[i]!.Equals(value)) return i; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                 }
             }
             return -1;
index a88fc2d..2a455a4 100644 (file)
@@ -13,6 +13,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Collections.ObjectModel
@@ -79,7 +80,7 @@ namespace System.Collections.ObjectModel
             }
         }
 
-        public bool TryGetValue(TKey key, out TValue value)
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
             return m_dictionary.TryGetValue(key, out value);
         }
@@ -272,7 +273,7 @@ namespace System.Collections.ObjectModel
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
             }
@@ -317,7 +318,7 @@ namespace System.Collections.ObjectModel
                     {
                         foreach (var item in m_dictionary)
                         {
-                            objects![index++] = new KeyValuePair<TKey, TValue>(item.Key, item.Value); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                            objects![index++] = new KeyValuePair<TKey, TValue>(item.Key, item.Value); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                         }
                     }
                     catch (ArrayTypeMismatchException)
@@ -348,7 +349,7 @@ namespace System.Collections.ObjectModel
                         Interlocked.CompareExchange<object?>(ref m_syncRoot, new object(), null);
                     }
                 }
-                return m_syncRoot!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34901
+                return m_syncRoot!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -429,7 +430,7 @@ namespace System.Collections.ObjectModel
                 {
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
                 }
-                m_collection = collection!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                m_collection = collection!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             #region ICollection<T> Members
@@ -514,10 +515,10 @@ namespace System.Collections.ObjectModel
                         }
                         else
                         {
-                            Interlocked.CompareExchange<object?>(ref m_syncRoot, new object(), null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34901
+                            Interlocked.CompareExchange<object?>(ref m_syncRoot, new object(), null);
                         }
                     }
-                    return m_syncRoot!;
+                    return m_syncRoot!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
                 }
             }
 
@@ -537,7 +538,7 @@ namespace System.Collections.ObjectModel
                 {
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
                 }
-                m_collection = collection!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                m_collection = collection!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             #region ICollection<T> Members
@@ -625,7 +626,7 @@ namespace System.Collections.ObjectModel
                             Interlocked.CompareExchange<object?>(ref m_syncRoot, new object(), null);
                         }
                     }
-                    return m_syncRoot!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34901
+                    return m_syncRoot!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
                 }
             }
 
@@ -646,7 +647,7 @@ namespace System.Collections.ObjectModel
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
             }
@@ -706,7 +707,7 @@ namespace System.Collections.ObjectModel
                 {
                     foreach (var item in collection)
                     {
-                        objects![index++] = item; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                        objects![index++] = item; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     }
                 }
                 catch (ArrayTypeMismatchException)
index 366afa6..ec58d55 100644 (file)
@@ -132,7 +132,7 @@ namespace System.Diagnostics.Tracing
                     {
                         if(payload[i] != null)
                         {
-                            sb.Append(payload[i]!.ToString()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                            sb.Append(payload[i]!.ToString()); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                         }
                         break;
                     }
index 36ddf53..6904765 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Buffers;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Threading;
@@ -32,6 +33,7 @@ namespace System
         // Note: The CLR's Watson bucketization code looks at the caller of the FCALL method
         // to assign blame for crashes.  Don't mess with this, such as by making it call 
         // another managed helper method, unless you consult with some CLR Watson experts.
+        [DoesNotReturn]
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern void FailFast(string? message);
 
@@ -48,9 +50,11 @@ namespace System
         //    if the exception object is preallocated, the runtime will use the callsite's
         //    IP for bucketing. If the exception object is not preallocated, it will use the bucket
         //    details contained in the object (if any).
+        [DoesNotReturn]
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern void FailFast(string? message, Exception? exception);
 
+        [DoesNotReturn]
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern void FailFast(string? message, Exception? exception, string? errorMessage);
 
index 762cfb2..7ec8014 100644 (file)
@@ -30,7 +30,7 @@ namespace System.IO
             else 
                 GetMessageForHR(hResult, JitHelpers.GetStringHandleOnStack(ref message));
 
-            return string.Format(format!, fileName, message!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 GetStringHandleOnStack needs to be attributed
+            return string.Format(format!, fileName, message!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
         }
 
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
index daae0fd..311c162 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -164,7 +165,7 @@ namespace System
             if (a[index] != null)
             {
                 MulticastDelegate d = (MulticastDelegate)o;
-                MulticastDelegate dd = (MulticastDelegate)a[index]!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                MulticastDelegate dd = (MulticastDelegate)a[index]!; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
 
                 if (dd._methodPtr == d._methodPtr &&
                     dd._target == d._target &&
@@ -566,6 +567,7 @@ namespace System
         }
 
         // this should help inlining
+        [DoesNotReturn]
         [System.Diagnostics.DebuggerNonUserCode]
         private void ThrowNullThisInDelegateToInstance()
         {
@@ -577,7 +579,7 @@ namespace System
         {
             if (target == null)
                 ThrowNullThisInDelegateToInstance();
-            this._target = target!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            this._target = target!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             this._methodPtr = methodPtr;
         }
 
index 8b0237c..eae84bf 100644 (file)
@@ -80,7 +80,7 @@ namespace System.Reflection
         {
             RuntimeAssembly? retAssembly = null;
             GetExecutingAssemblyNative(JitHelpers.GetStackCrawlMarkHandle(ref stackMark), JitHelpers.GetObjectHandleOnStack(ref retAssembly));
-            return retAssembly!; // TODO-NULLABLE: Confirm this can never be null
+            return retAssembly!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
         }
 
         // Get the assembly that the current code is running from.
index 777ad2a..9c4e5ca 100644 (file)
@@ -1038,7 +1038,7 @@ namespace System.Reflection.Emit
         public int GetTokenFor(RuntimeMethodHandle method)
         {
             IRuntimeMethodInfo methodReal = method.GetMethodInfo();
-            if (methodReal != null) // TODO-NULLABLE: never null
+            if (methodReal != null)
             {
                 RuntimeMethodHandleInternal rmhi = methodReal.Value;
                 if (!RuntimeMethodHandle.IsDynamicMethod(rmhi))
index 978f234..6a8c340 100644 (file)
@@ -706,7 +706,7 @@ namespace System.Reflection.Emit
                 get { return m_owner.IsSecurityTransparent; }
             }
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
             public override Type ReturnType
             {
                 get
@@ -721,7 +721,7 @@ namespace System.Reflection.Emit
                 get { return null; }
             }
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
             public override ICustomAttributeProvider ReturnTypeCustomAttributes
             {
                 get { return GetEmptyCAHolder(); }
index 6138e55..a363f46 100644 (file)
@@ -1564,7 +1564,7 @@ namespace System.Reflection.Emit
             {
                 m_localSymInfos[i] = new LocalSymInfo();
             }
-            m_localSymInfos[i]!.AddLocalSymInfo(strName, signature, slot, startOffset, endOffset); // TODO-NULLABLE https://github.com/dotnet/roslyn/issues/34644
+            m_localSymInfos[i]!.AddLocalSymInfo(strName, signature, slot, startOffset, endOffset); // TODO-NULLABLE Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
         }
 
         internal void AddUsingNamespaceToCurrentScope(
@@ -1575,7 +1575,7 @@ namespace System.Reflection.Emit
             {
                 m_localSymInfos[i] = new LocalSymInfo();
             }
-            m_localSymInfos[i]!.AddUsingNamespace(strNamespace); // TODO-NULLABLE https://github.com/dotnet/roslyn/issues/34644
+            m_localSymInfos[i]!.AddUsingNamespace(strNamespace); // TODO-NULLABLE Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
         }
 
         internal void AddScopeInfo(ScopeAction sa, int iOffset)
@@ -1642,7 +1642,7 @@ namespace System.Reflection.Emit
                 }
                 if (m_localSymInfos[i] != null)
                 {
-                    m_localSymInfos[i]!.EmitLocalSymInfo(symWriter); // TODO-NULLABLE https://github.com/dotnet/roslyn/issues/34644
+                    m_localSymInfos[i]!.EmitLocalSymInfo(symWriter); // TODO-NULLABLE Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                 }
             }
         }
index e8c58b7..faa404b 100644 (file)
@@ -57,7 +57,7 @@ namespace System.Reflection.Emit
                 m_pDocumentWriterSafeHandle = pDocumentWriterSafeHandle;
                 // The handle is actually a pointer to a native ISymUnmanagedDocumentWriter.
                 m_pDocWriter = (ISymUnmanagedDocumentWriter*)m_pDocumentWriterSafeHandle.DangerousGetHandle();
-                m_vtable = (ISymUnmanagedDocumentWriterVTable)(Marshal.PtrToStructure(m_pDocWriter->m_unmanagedVTable, typeof(ISymUnmanagedDocumentWriterVTable)))!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                m_vtable = (ISymUnmanagedDocumentWriterVTable)(Marshal.PtrToStructure(m_pDocWriter->m_unmanagedVTable, typeof(ISymUnmanagedDocumentWriterVTable)))!;
             }
 
             //------------------------------------------------------------------------------
@@ -358,7 +358,7 @@ namespace System.Reflection.Emit
             internal void InternalSetUnderlyingWriter(IntPtr ppUnderlyingWriter)
             {
                 m_pWriter = *((ISymUnmanagedWriter**)ppUnderlyingWriter);
-                m_vtable = (ISymUnmanagedWriterVTable)(Marshal.PtrToStructure(m_pWriter->m_unmanagedVTable, typeof(ISymUnmanagedWriterVTable)))!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                m_vtable = (ISymUnmanagedWriterVTable)(Marshal.PtrToStructure(m_pWriter->m_unmanagedVTable, typeof(ISymUnmanagedWriterVTable)))!;
             }
 
             //------------------------------------------------------------------------------
index abf38ab..63e570c 100644 (file)
@@ -270,7 +270,7 @@ namespace System.Reflection.Emit
                 // if it is in a debug module
                 //
                 SymbolToken tk = new SymbolToken(MetadataTokenInternal);
-                ISymbolWriter symWriter = dynMod.GetSymWriter()!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                ISymbolWriter symWriter = dynMod.GetSymWriter()!;
 
                 // call OpenMethod to make this method the current method
                 symWriter.OpenMethod(tk);
index b3390c0..9f99bad 100644 (file)
@@ -391,7 +391,7 @@ namespace System.Reflection.Emit
             get { return m_baseType.Namespace; }
         }
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
         public override Type BaseType
         {
             get { return typeof(System.Array); }
index a9f8065..d5eda80 100644 (file)
@@ -50,7 +50,7 @@ namespace System.Reflection
                 {
                     Interlocked.CompareExchange<object?>(ref m_syncRoot, new object(), null);
                 }
-                return m_syncRoot!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return m_syncRoot!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -728,7 +728,7 @@ namespace System.Reflection
                     exception = e;
                 }
 
-                Debug.Assert((type != null) != (exception != null)); // Exactly one of these must be non-null. // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                Debug.Assert((type != null) != (exception != null)); // Exactly one of these must be non-null.
 
                 if (type != null)
                 {
index 768e4a7..5d8be5d 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Text;
 using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
@@ -328,6 +329,7 @@ namespace System.Reflection
                 throw new MemberAccessException(SR.Access_Void);
         }
 
+        [DoesNotReturn]
         internal void ThrowNoInvokeException()
         {
             CheckCanCreateInstance(DeclaringType!, (CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs);
index 7ba7576..f60779f 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Security;
 using System.Text;
@@ -418,6 +419,7 @@ namespace System.Reflection
             }
         }
 
+        [DoesNotReturn]
         private void ThrowNoInvokeException()
         {
             // method is on a class that contains stack pointers
@@ -507,7 +509,7 @@ namespace System.Reflection
 
         #region MethodInfo Overrides
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
         public override Type ReturnType
         {
             get { return Signature.ReturnType; }
index 0bad3f6..c22229a 100644 (file)
@@ -14,6 +14,7 @@ using System.Threading;
 using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute;
 using MdToken = System.Reflection.MetadataToken;
 using Internal.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System
 {
@@ -135,7 +136,7 @@ namespace System
                         _capacity = newCapacity;
                     }
 
-                    _items![_count] = item; // TODO-NULLABLE: https://github.com/dotnet/coreclr/pull/23708
+                    _items![_count] = item; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
                 _count++;
             }
@@ -1434,7 +1435,7 @@ namespace System
             #endregion
 
             #region Private Members
-            private string ConstructName(ref string? name, TypeNameFormatFlags formatFlags) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            private string ConstructName([NotNull] ref string? name, TypeNameFormatFlags formatFlags)
             {
                 if (name == null)
                 {
@@ -4195,7 +4196,7 @@ namespace System
 
                 MethodBase? invokeMethod = null;
 
-                try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs!, modifiers, culture, namedParams, out state); } //TODO-NULLABLE https://github.com/dotnet/csharplang/issues/2388
+                try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs!, modifiers, culture, namedParams, out state); }
                 catch (MissingMethodException) { }
 
                 if (invokeMethod == null)
@@ -4204,7 +4205,7 @@ namespace System
                 object? result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
 
                 if (state != null)
-                    binder.ReorderArgumentArray(ref providedArgs!, state);
+                    binder.ReorderArgumentArray(ref providedArgs!, state); // TODO-NULLABLE: Pass non-null string? to string ref (https://github.com/dotnet/roslyn/issues/34874)
 
                 return result;
             }
@@ -4384,7 +4385,7 @@ namespace System
                 {
                     if (args[i] != null)
                     {
-                        argsType[i] = args[i]!.GetType(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        argsType[i] = args[i]!.GetType(); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                     }
                 }
 
@@ -4406,7 +4407,7 @@ namespace System
 
                 try
                 {
-                    invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args!, null, culture, null, out state); //TODO-NULLABLE https://github.com/dotnet/csharplang/issues/2388
+                    invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args!, null, culture, null, out state); //TODO-NULLABLE: Pass non-null string? to string ref (https://github.com/dotnet/roslyn/issues/34874)
                 }
                 catch (MissingMethodException) { invokeMethod = null; }
 
index 4b1b543..d996d44 100644 (file)
@@ -2,9 +2,11 @@
 // 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.Diagnostics.CodeAnalysis;
+
 namespace System.Runtime.CompilerServices
 {
-    
+
     /// <summary>
     /// Helpers that allows VM to call into ICastable methods without having to deal with RuntimeTypeHandle.
     /// RuntimeTypeHandle is a struct and is always passed in stack in x86, which our VM call helpers don't
@@ -12,7 +14,7 @@ namespace System.Runtime.CompilerServices
     /// </summary>
     internal class ICastableHelpers
     {
-        internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, out Exception? castError) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, [NotNullWhen(true)] out Exception? castError)
         {
             return castable.IsInstanceOfInterface(new RuntimeTypeHandle(type), out castError);
         }
index bf792c3..81fae84 100644 (file)
@@ -10,6 +10,7 @@
 using System.Threading;
 using System.Diagnostics;
 using Internal.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.CompilerServices
 {
@@ -107,14 +108,14 @@ namespace System.Runtime.CompilerServices
 
         // Wraps object variable into a handle. Used to return managed strings from QCalls.
         // s has to be a local variable on the stack.
-        internal static StringHandleOnStack GetStringHandleOnStack(ref string? s)
+        internal static StringHandleOnStack GetStringHandleOnStack([NotNull] ref string? s)
         {
             return new StringHandleOnStack((IntPtr)Unsafe.AsPointer(ref s));
         }
 
         // Wraps object variable into a handle. Used to pass managed object references in and out of QCalls.
         // o has to be a local variable on the stack.
-        internal static ObjectHandleOnStack GetObjectHandleOnStack<T>(ref T o) where T : class?
+        internal static ObjectHandleOnStack GetObjectHandleOnStack<T>([NotNull] ref T o) where T : class?
         {
             return new ObjectHandleOnStack((IntPtr)Unsafe.AsPointer(ref o));
         }
index 20a4cc5..b8a6dd8 100644 (file)
@@ -55,7 +55,7 @@ namespace System.Runtime.InteropServices
                     {
                         if (_cachedTargetTypes[i] != null)
                         {
-                            args[i] = Enum.ToObject(_cachedTargetTypes[i]!, args[i]); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                            args[i] = Enum.ToObject(_cachedTargetTypes[i]!, args[i]); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                         }
                     }
                 }
@@ -173,7 +173,7 @@ namespace System.Runtime.InteropServices
                 {
                     if (wrapper.Delegate.GetType() == d.GetType())
                     {
-                        wrapper.Delegate = Delegate.Combine(wrapper.Delegate, d)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        wrapper.Delegate = Delegate.Combine(wrapper.Delegate, d)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         return;
                     }
                 }
index 21116e4..6b1c418 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Runtime.InteropServices.CustomMarshalers
             _current = null;
         }
 
-        public object? Current => _current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        public object? Current => _current;
 
         public unsafe bool MoveNext()
         {
index cecf880..6df19ae 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.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.ConstrainedExecution;
@@ -349,8 +350,7 @@ namespace System.Runtime.InteropServices
             return GetComInterfaceForObjectNative(o, T, false, true);
         }
 
-        // TODO-NULLABLE-GENERIC: T cannot be null
-        public static IntPtr GetComInterfaceForObject<T, TInterface>(T o) => GetComInterfaceForObject(o!, typeof(TInterface));
+        public static IntPtr GetComInterfaceForObject<T, TInterface>([DisallowNull] T o) => GetComInterfaceForObject(o!, typeof(TInterface));
 
         /// <summary>
         /// Return the IUnknown* representing the interface for the Object.
@@ -388,10 +388,9 @@ namespace System.Runtime.InteropServices
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, object o);
 
-        public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o)
+        public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o) where T : object
         {
-            // TODO-NULLABLE-GENERIC: T cannot be null
-            return CreateAggregatedObject(pOuter, (object)o!);
+            return CreateAggregatedObject(pOuter, (object)o);
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -641,9 +640,8 @@ namespace System.Runtime.InteropServices
             return Wrapper;
         }
 
-        public static TWrapper CreateWrapperOfType<T, TWrapper>(T o)
+        public static TWrapper CreateWrapperOfType<T, TWrapper>([AllowNull] T o)
         {
-            // TODO-NULLABLE-GENERIC: T can be null
             return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper))!;
         }
 
@@ -668,25 +666,23 @@ namespace System.Runtime.InteropServices
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern void GetNativeVariantForObject(object? obj, /* VARIANT * */ IntPtr pDstNativeVariant);
 
-        public static void GetNativeVariantForObject<T>(T obj, IntPtr pDstNativeVariant)
+        public static void GetNativeVariantForObject<T>([AllowNull] T obj, IntPtr pDstNativeVariant)
         {
-            // TODO-NULLABLE-GENERIC: T can be null
-            GetNativeVariantForObject((object)obj!, pDstNativeVariant);
+            GetNativeVariantForObject((object?)obj, pDstNativeVariant);
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern object? GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant);
 
+        [return: MaybeNull]
         public static T GetObjectForNativeVariant<T>(IntPtr pSrcNativeVariant)
         {
-            // TODO-NULLABLE-GENERIC: T can be null
             return (T)GetObjectForNativeVariant(pSrcNativeVariant)!;
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern object?[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars);
 
-        // TODO-NULLABLE-GENERIC: T[] contents can be null
         public static T[] GetObjectsForNativeVariants<T>(IntPtr aSrcNativeVariant, int cVars)
         {
             object?[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars);
index dc4028a..8ee1ff7 100644 (file)
@@ -37,7 +37,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
 
         object IGetProxyTarget.GetTarget()
         {
-            return _value!; // TODO-NULLABLE-GENERIC
+            return _value!;
         }
 
         // We have T in an IReference<T>.  Need to QI for IReference<T> with the appropriate GUID, call
@@ -50,7 +50,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             Debug.Assert(wrapper != null);
             IReference<T> reference = (IReference<T>)wrapper;
             Debug.Assert(reference != null, "CLRIReferenceImpl::UnboxHelper - QI'ed for IReference<" + typeof(T) + ">, but that failed.");
-            return reference.Value!; // TODO-NULLABLE-GENERIC
+            return reference.Value!;
         }
     }
 
index 5c4aaf7..9f5f99b 100644 (file)
@@ -5,6 +5,7 @@
 using System.Diagnostics;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.InteropServices.WindowsRuntime
 {
@@ -145,14 +146,14 @@ namespace System.Runtime.InteropServices.WindowsRuntime
 
         #region IReadOnlyDictionary members
 
-        public bool TryGetValue(TKey key, out TValue value)
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
-            KeyValuePair<TKey, TValue> searchKey = new KeyValuePair<TKey, TValue>(key, default!); // TODO-NULLABLE-GENERIC
+            KeyValuePair<TKey, TValue> searchKey = new KeyValuePair<TKey, TValue>(key, default!);
             int index = Array.BinarySearch(items, firstItemIndex, Count, searchKey, keyValuePairComparator);
 
             if (index < 0)
             {
-                value = default!; // TODO-NULLABLE-GENERIC
+                value = default!;
                 return false;
             }
 
@@ -205,7 +206,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                 }
             }
 
-            object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+            object? IEnumerator.Current
             {
                 get
                 {
index 7fe627d..f9eb669 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Runtime.InteropServices.WindowsRuntime
@@ -17,7 +18,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
 
         // Cached multicast delegate which will invoke all of the currently registered delegates.  This
         // will be accessed frequently in common coding paterns, so we don't want to calculate it repeatedly.
-        private volatile T m_invokeList = null!; // TODO-NULLABLE-GENERIC
+        [AllowNull, MaybeNull] private volatile T m_invokeList = null!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
         public EventRegistrationTokenTable()
         {
@@ -31,20 +32,20 @@ namespace System.Runtime.InteropServices.WindowsRuntime
 
         // The InvocationList property provides access to a delegate which will invoke every registered event handler
         // in this table.  If the property is set, the new value will replace any existing token registrations.
+        [MaybeNull]
         public T InvocationList
         {
             get
             {
                 return m_invokeList;
             }
-
             set
             {
                 lock (m_tokens)
                 {
                     // The value being set replaces any of the existing values
                     m_tokens.Clear();
-                    m_invokeList = null!; // TODO-NULLABLE-GENERIC
+                    m_invokeList = null!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
                     if (value != null)
                     {
@@ -84,7 +85,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             // Update the current invocation list to include the newly added delegate
             Delegate? invokeList = (Delegate?)(object?)m_invokeList;
             invokeList = MulticastDelegate.Combine(invokeList, (Delegate)(object)handler);
-            m_invokeList = (T)(object?)invokeList!; // TODO-NULLABLE-GENERIC
+            m_invokeList = (T)(object?)invokeList!;
 
             return token;
         }
@@ -235,7 +236,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                 // Update the current invocation list to remove the delegate
                 Delegate? invokeList = (Delegate?)(object?)m_invokeList;
                 invokeList = MulticastDelegate.Remove(invokeList, (Delegate?)(object?)handler);
-                m_invokeList = (T)(object?)invokeList!; // TODO-NULLABLE-GENERIC
+                m_invokeList = (T)(object?)invokeList!;
             }
         }
 
@@ -245,7 +246,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             {
                 Interlocked.CompareExchange(ref refEventTable, new EventRegistrationTokenTable<T>(), null);
             }
-            return refEventTable!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            return refEventTable!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
         }
     }
 }
index 16ef392..7a8b11b 100644 (file)
@@ -5,6 +5,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using Internal.Runtime.CompilerServices;
 
 namespace System.Runtime.InteropServices.WindowsRuntime
@@ -62,7 +63,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
         }
 
         // bool TryGetValue(TKey key, out TValue value)
-        internal bool TryGetValue<K, V>(K key, out V value) where K : object
+        internal bool TryGetValue<K, V>(K key, [MaybeNullWhen(false)] out V value) where K : object
         {
             if (key == null)
                 throw new ArgumentNullException(nameof(key));
@@ -73,7 +74,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             // throw an exception from Lookup.
             if (!_this.HasKey(key))
             {
-                value = default!; // TODO-NULLABLE-GENERIC
+                value = default!;
                 return false;
             }
 
@@ -86,7 +87,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             {
                 if (HResults.E_BOUNDS == ex.HResult)
                 {
-                    value = default!; // TODO-NULLABLE-GENERIC
+                    value = default!;
                     return false;
                 }
                 throw;
index 756026b..9c9245e 100644 (file)
@@ -98,7 +98,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
     {
         private IIterator<T> m_iterator;
         private bool m_hadCurrent;
-        private T m_current = default!; // TODO-NULLABLE-GENERIC
+        private T m_current = default!;
         private bool m_isInitialized;
 
         internal IteratorToEnumeratorAdapter(IIterator<T> iterator)
index a5e5673..e0ad2d7 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using Internal.Runtime.CompilerServices;
 
 namespace System.Runtime.InteropServices.WindowsRuntime
@@ -110,7 +111,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
         }
 
         // bool TryGetValue(TKey key, out TValue value)
-        internal bool TryGetValue<K, V>(K key, out V value) where K : object
+        internal bool TryGetValue<K, V>(K key, [MaybeNullWhen(false)] out V value) where K : object
         {
             if (key == null)
                 throw new ArgumentNullException(nameof(key));
@@ -118,7 +119,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             IMap<K, V> _this = Unsafe.As<IMap<K, V>>(this);
             if (!_this.HasKey(key))
             {
-                value = default!; // TODO-NULLABLE-GENERIC
+                value = default!;
                 return false;
             }
 
@@ -129,7 +130,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             }
             catch (KeyNotFoundException)
             {
-                value = default!; // TODO-NULLABLE-GENERIC
+                value = default!;
                 return false;
             }
         }
index d879f89..7f5fef2 100644 (file)
@@ -531,7 +531,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                 return (object)Marshal.GetRawIUnknownForComObjectNoAddRef(target);
             }
 
-            private static object? FindEquivalentKeyUnsafe(ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTable, object handler, out EventRegistrationTokenListWithCount? tokens) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            private static object? FindEquivalentKeyUnsafe(ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTable, object handler, out EventRegistrationTokenListWithCount? tokens)
             {
                 foreach (KeyValuePair<object, EventRegistrationTokenListWithCount> item in registrationTable)
                 {
@@ -599,7 +599,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                             }
                             else
                             {
-                                tokens!.Push(token); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                                tokens!.Push(token);
                             }
 
                             tokenAdded = true;
@@ -742,7 +742,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                             // NOTE: We should not check whether registrationTokens has 0 entries and remove it from the cache
                             // (just like managed event implementation), because this might have raced with the finalizer of
                             // EventRegistrationTokenList
-                            registrationTokens.Remove(key!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                            registrationTokens.Remove(key!);
                         }
 
                         Log("[WinRT_Eventing] Event unsubscribed for managed instance = " + instanceKey + ", handler = " + handler + ", token = " + token.Value + "\n");
index 6fdb5da..ad9f585 100644 (file)
@@ -99,13 +99,13 @@ namespace System.Runtime.Loader
             _assemblyPaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
             foreach (string assemblyPath in assemblyPaths)
             {
-                _assemblyPaths.Add(Path.GetFileNameWithoutExtension(assemblyPath)!, assemblyPath); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                _assemblyPaths.Add(Path.GetFileNameWithoutExtension(assemblyPath)!, assemblyPath); // TODO-NULLABLE: Remove ! when nullable attributes are respected
             }
 
             _nativeSearchPaths = SplitPathsList(nativeSearchPathsList);
             _resourceSearchPaths = SplitPathsList(resourceSearchPathsList);
 
-            _assemblyDirectorySearchPaths = new string[1] { Path.GetDirectoryName(componentAssemblyPath)! }; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            _assemblyDirectorySearchPaths = new string[1] { Path.GetDirectoryName(componentAssemblyPath)! };
         }
 
         public string? ResolveAssemblyToPath(AssemblyName assemblyName)
index 94d7ba9..0f9ee4e 100644 (file)
@@ -1622,7 +1622,7 @@ namespace System.StubHelpers
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.pHandle, ExceptionResource.ArgumentNull_SafeHandle);
             }
 
-            pHandle!.DangerousAddRef(ref success); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            pHandle!.DangerousAddRef(ref success); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             return pHandle.DangerousGetHandle();
         }
 
@@ -1636,7 +1636,7 @@ namespace System.StubHelpers
 
             try
             {
-                pHandle!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                pHandle!.DangerousRelease(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             catch
             {
index ed6829e..f23942e 100644 (file)
@@ -5,6 +5,7 @@
 using System.Runtime.CompilerServices;
 using Internal.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Threading
 {
@@ -59,7 +60,8 @@ namespace System.Threading
         public static extern double Exchange(ref double location1, double value);
 
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
-        public static extern object? Exchange(ref object? location1, object? value);
+        [return: NotNullIfNotNull("value")]
+        public static extern object? Exchange([NotNullIfNotNull("value")] ref object? location1, object? value);
 
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
         public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value);
@@ -67,7 +69,8 @@ namespace System.Threading
         // This whole method reduces to a single call to Exchange(ref object, object) but
         // the JIT thinks that it will generate more native code than it actually does.
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static T Exchange<T>(ref T location1, T value) where T : class?
+        [return: NotNullIfNotNull("value")]
+        public static T Exchange<T>([NotNullIfNotNull("value")] ref T location1, T value) where T : class?
         {
             return Unsafe.As<T>(Exchange(ref Unsafe.As<T, object?>(ref location1), value));
         }
index 4385bf9..1783d4d 100644 (file)
@@ -21,6 +21,7 @@ using System.Runtime.ConstrainedExecution;
 using System.Runtime.Versioning;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Threading
 {
@@ -52,6 +53,7 @@ namespace System.Threading
             Debug.Assert(lockTaken);
         }
 
+        [DoesNotReturn]
         private static void ThrowLockTakenException()
         {
             throw new ArgumentException(SR.Argument_MustBeFalse, "lockTaken");
index 53d47b9..ec82665 100644 (file)
@@ -52,7 +52,7 @@ namespace System.Threading
             m_internalWaitObject = waitObject;
             if (waitObject != null)
             {
-                m_internalWaitObject.SafeWaitHandle!.DangerousAddRef(ref bReleaseNeeded); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+                m_internalWaitObject.SafeWaitHandle.DangerousAddRef(ref bReleaseNeeded);
             }
         }
 
@@ -82,7 +82,7 @@ namespace System.Threading
                                 if (bReleaseNeeded)
                                 {
                                     Debug.Assert(m_internalWaitObject != null, "Must be non-null for bReleaseNeeded to be true");
-                                    m_internalWaitObject.SafeWaitHandle!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+                                    m_internalWaitObject.SafeWaitHandle.DangerousRelease();
                                     bReleaseNeeded = false;
                                 }
                                 // if result not true don't release/suppress here so finalizer can make another attempt
@@ -144,7 +144,7 @@ namespace System.Threading
                         if (bReleaseNeeded)
                         {
                             Debug.Assert(m_internalWaitObject != null, "Must be non-null for bReleaseNeeded to be true");
-                            m_internalWaitObject.SafeWaitHandle!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+                            m_internalWaitObject.SafeWaitHandle.DangerousRelease();
                             bReleaseNeeded = false;
                         }
                         SetHandle(InvalidHandle);
index 4705216..c448b5b 100644 (file)
@@ -49,7 +49,7 @@ namespace System
 
             Utf8String newString = FastAllocate(value.Length);
             Buffer.Memmove(ref newString.DangerousGetMutableReference(), ref MemoryMarshal.GetReference(value), (uint)value.Length);
-            return Utf8Utility.ValidateAndFixupUtf8String(newString)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            return Utf8Utility.ValidateAndFixupUtf8String(newString)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
         }
 
         /// <summary>
index 7a1a17c..83a4b39 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.ComponentModel;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Text;
 using Internal.Runtime.CompilerServices;
@@ -13,7 +14,7 @@ namespace System
     /// <summary>
     /// Represents an immutable string of UTF-8 code units.
     /// </summary>
-    public sealed partial class Utf8String : IEquatable<Utf8String?>
+    public sealed partial class Utf8String : IEquatable<Utf8String>
     {
         /*
          * STATIC FIELDS
@@ -118,7 +119,9 @@ namespace System
         /// <summary>
         /// Performs an equality comparison using a <see cref="StringComparison.Ordinal"/> comparer.
         /// </summary>
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
         public bool Equals(Utf8String? value)
+#pragma warning restore CS8614
         {
             // First, a very quick check for referential equality.
 
@@ -179,7 +182,7 @@ namespace System
         /// Returns <see langword="true"/> if <paramref name="value"/> is <see langword="null"/> or zero length;
         /// <see langword="false"/> otherwise.
         /// </summary>
-        public static bool IsNullOrEmpty(Utf8String? value)
+        public static bool IsNullOrEmpty([NotNullWhen(false)] Utf8String? value)
         {
             // Copied from String.IsNullOrEmpty. See that method for detailed comments on why this pattern is used.
             return (value is null || 0u >= (uint)value.Length) ? true : false;
index 7b89b05..1413a35 100644 (file)
@@ -15,6 +15,7 @@ using System.Security;
 using System.Runtime;
 using System.Runtime.CompilerServices;
 using System.Runtime.Versioning;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System
 {
@@ -51,7 +52,7 @@ namespace System
                 throw new ArgumentNullException(nameof(info));
             }
 
-            T target = (T)info.GetValue("TrackedObject", typeof(T))!; // Do not rename (binary serialization) // TODO-NULLABLE-GENERIC
+            T target = (T)info.GetValue("TrackedObject", typeof(T))!; // Do not rename (binary serialization)
             bool trackResurrection = info.GetBoolean("TrackResurrection"); // Do not rename (binary serialization)
 
             Create(target, trackResurrection);
@@ -65,7 +66,7 @@ namespace System
         //          DoSomething(ref.Target)
         //
         [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
-        public bool TryGetTarget(out T target)
+        public bool TryGetTarget([NotNullWhen(true)] out T target)
         {
             // Call the worker method that has more performant but less user friendly signature.
             T o = this.Target;
index 6ea8cf9..912ddce 100644 (file)
@@ -6,6 +6,7 @@ using System;
 using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Security;
 
@@ -219,7 +220,8 @@ namespace Internal.Win32
             return GetValue(name, null);
         }
 
-        public object? GetValue(string name, object? defaultValue) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("defaultValue")]
+        public object? GetValue(string name, object? defaultValue)
         {
             object? data = defaultValue;
             int type = 0;
@@ -369,7 +371,7 @@ namespace Internal.Win32
                         // make sure the string is null terminated before processing the data
                         if (blob.Length > 0 && blob[blob.Length - 1] != (char)0)
                         {
-                            Array.Resize(ref blob!, blob.Length + 1); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            Array.Resize(ref blob!, blob.Length + 1); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         }
 
                         string[] strings = Array.Empty<string>();
@@ -414,13 +416,13 @@ namespace Internal.Win32
                             {
                                 if (strings.Length == stringsCount)
                                 {
-                                    Array.Resize(ref strings!, stringsCount > 0 ? stringsCount * 2 : 4); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                                    Array.Resize(ref strings!, stringsCount > 0 ? stringsCount * 2 : 4); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                                 }
-                                strings![stringsCount++] = toAdd; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                                strings![stringsCount++] = toAdd; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                             }
                         }
 
-                        Array.Resize(ref strings!, stringsCount); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        Array.Resize(ref strings!, stringsCount); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         data = strings;
                     }
                     break;
index 3022329..2e597e7 100644 (file)
@@ -145,9 +145,7 @@ internal static partial class Interop
             return Interop.Sys.StrError(RawErrno);
         }
 
-#pragma warning disable CS8609 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
         public override string ToString()
-#pragma warning restore CS8609
         {
             return $"RawErrno: {RawErrno} Error: {Error} GetErrorMessage: {GetErrorMessage()}"; // No localization required; text is member names used for debugging purposes
         }
index 212d515..a2fe207 100644 (file)
@@ -27,13 +27,13 @@ internal static partial class Interop
                 {
                     if (count == found.Length)
                     {
-                        Array.Resize(ref found!, count * 2); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        Array.Resize(ref found!, count * 2); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     }
                     found[count++] = Marshal.PtrToStringAnsi((IntPtr)name)!;
                 });
             }
 
-            Array.Resize(ref found!, count); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Array.Resize(ref found!, count); // TODO-NULLABLE: Remove ! when nullable attributes are respected
             return found;
         }
     }
index d925be1..de68a36 100644 (file)
@@ -4,7 +4,6 @@
 
 using Microsoft.Win32.SafeHandles;
 using System;
-using System.Diagnostics;
 using System.IO;
 using System.Runtime.InteropServices;
 
@@ -34,9 +33,8 @@ internal partial class Interop
             int dwFlagsAndAttributes,
             IntPtr hTemplateFile)
         {
-            string? lpFileNameWithPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(lpFileName);
-            Debug.Assert(lpFileNameWithPrefix != null, "null not expected when non-null passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
-            return CreateFilePrivate(lpFileNameWithPrefix, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+            lpFileName = PathInternal.EnsureExtendedPrefixIfNeeded(lpFileName)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
+            return CreateFilePrivate(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
         }
     }
 }
index 8866982..49e7485 100644 (file)
@@ -26,9 +26,8 @@ internal partial class Interop
             FileMode dwCreationDisposition,
             ref Kernel32.CREATEFILE2_EXTENDED_PARAMETERS pCreateExParams)
         {
-            string? lpFileNameWithPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(lpFileName);
-            Debug.Assert(lpFileNameWithPrefix != null, "null not expected when non-null passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
-            return CreateFile2Private(lpFileNameWithPrefix, dwDesiredAccess, dwShareMode, dwCreationDisposition, ref pCreateExParams);
+            lpFileName = PathInternal.EnsureExtendedPrefixIfNeeded(lpFileName)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
+            return CreateFile2Private(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, ref pCreateExParams);
         }
     }
 }
index 80fb2e7..52dcd54 100644 (file)
@@ -21,11 +21,10 @@ internal partial class Interop
 
         internal static SafeFindHandle FindFirstFile(string fileName, ref WIN32_FIND_DATA data)
         {
-            string? fileNameWithPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(fileName);
-            Debug.Assert(fileNameWithPrefix != null, "null not expected when non-null passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            fileName = PathInternal.EnsureExtendedPrefixIfNeeded(fileName)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
             // use FindExInfoBasic since we don't care about short name and it has better perf
-            return FindFirstFileExPrivate(fileNameWithPrefix, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0);
+            return FindFirstFileExPrivate(fileName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0);
         }
 
         internal enum FINDEX_INFO_LEVELS : uint
index b833e8b..e3f18fe 100644 (file)
@@ -21,9 +21,8 @@ internal partial class Interop
 
         internal static bool GetFileAttributesEx(string name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation)
         {
-            string? nameWithExtendedPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(name);
-            Debug.Assert(nameWithExtendedPrefix != null, "null not expected when non-null is passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
-            return GetFileAttributesExPrivate(nameWithExtendedPrefix, fileInfoLevel, ref lpFileInformation);
+            name = PathInternal.EnsureExtendedPrefixIfNeeded(name)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
+            return GetFileAttributesExPrivate(name, fileInfoLevel, ref lpFileInformation);
         }
     }
 }
index 2edb4b3..0b8bdde 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\DefaultBinder.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Delegate.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\CodeAnalysis\SuppressMessageAttribute.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\CodeAnalysis\NullableAttributes.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\ConditionalAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Contracts\ContractException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Contracts\ContractFailedEventArgs.cs" />
index 15b7351..7f81a43 100644 (file)
@@ -126,7 +126,7 @@ namespace System
                 Interlocked.CompareExchange(ref s_switches, new Dictionary<string, bool>(), null);
             }
 
-            lock (s_switches!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            lock (s_switches!) // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             {
                 s_switches[switchName] = isEnabled;
             }
index 0884c61..2d8cd9c 100644 (file)
@@ -409,7 +409,7 @@ namespace System
                                 (Func<IPrincipal>)mi.CreateDelegate(typeof(Func<IPrincipal>)));
                         }
 
-                        principal = s_getUnauthenticatedPrincipal!(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        principal = s_getUnauthenticatedPrincipal!(); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         break;
 
                     case PrincipalPolicy.WindowsPrincipal:
@@ -425,7 +425,7 @@ namespace System
                                 (Func<IPrincipal>)mi.CreateDelegate(typeof(Func<IPrincipal>)));
                         }
 
-                        principal = s_getWindowsPrincipal!(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        principal = s_getWindowsPrincipal!(); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         break;
                 }
             }
index 049385b..11479d8 100644 (file)
@@ -6,6 +6,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using Internal.Runtime.CompilerServices;
@@ -36,10 +37,10 @@ namespace System
             }
 
             // T[] implements IList<T>.
-            return new ReadOnlyCollection<T>(array!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return new ReadOnlyCollection<T>(array!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
-        public static void Resize<T>(ref T[]? array, int newSize) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static void Resize<T>([NotNull] ref T[]? array, int newSize)
         {
             if (newSize < 0)
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.newSize, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
@@ -65,7 +66,7 @@ namespace System
             {
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
             }
-            if (lengths!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (lengths!.Length == 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
 
             int[] intLengths = new int[lengths.Length];
@@ -149,7 +150,7 @@ namespace System
         {
             if (indices == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
-            if (Rank != indices!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (Rank != indices!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
 
             int[] intIndices = new int[indices.Length];
@@ -209,7 +210,7 @@ namespace System
         {
             if (indices == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
-            if (Rank != indices!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (Rank != indices!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
 
             int[] intIndices = new int[indices.Length];
@@ -324,7 +325,7 @@ namespace System
             int i = 0;
             int c = 0;
 
-            while (i < o!.Length && c == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            while (i < o!.Length && c == 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 object? left = GetValue(i);
                 object? right = o.GetValue(i);
@@ -383,7 +384,7 @@ namespace System
 
             for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++)
             {
-                ret = CombineHashCodes(ret, comparer!.GetHashCode(GetValue(i)!)); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                ret = CombineHashCodes(ret, comparer!.GetHashCode(GetValue(i)!)); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             return ret;
@@ -406,7 +407,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            return BinarySearch(array!, array!.GetLowerBound(0), array.Length, value, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return BinarySearch(array!, array!.GetLowerBound(0), array.Length, value, null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Searches a section of an array for a given element using a binary search
@@ -445,7 +446,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            return BinarySearch(array!, array!.GetLowerBound(0), array.Length, value, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return BinarySearch(array!, array!.GetLowerBound(0), array.Length, value, comparer); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Searches a section of an array for a given element using a binary search
@@ -467,7 +468,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (index < lb)
                 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
             if (length < 0)
@@ -552,14 +553,14 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            return BinarySearch<T>(array!, 0, array!.Length, value, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return BinarySearch<T>(array!, 0, array!.Length, value, null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int BinarySearch<T>(T[] array, T value, System.Collections.Generic.IComparer<T>? comparer)
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            return BinarySearch<T>(array!, 0, array!.Length, value, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return BinarySearch<T>(array!, 0, array!.Length, value, comparer); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int BinarySearch<T>(T[] array, int index, int length, T value)
@@ -576,7 +577,7 @@ namespace System
             if (length < 0)
                 ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
 
-            if (array!.Length - index < length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Length - index < length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
 
             return ArraySortHelper<T>.Default.BinarySearch(array, index, length, value, comparer);
@@ -594,10 +595,10 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
             }
 
-            TOutput[] newArray = new TOutput[array!.Length]; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            TOutput[] newArray = new TOutput[array!.Length]; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             for (int i = 0; i < array.Length; i++)
             {
-                newArray[i] = converter!(array[i]); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                newArray[i] = converter!(array[i]); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             return newArray;
         }
@@ -614,7 +615,7 @@ namespace System
             if (array != null && array.Rank != 1)
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
             // Note: Array.Copy throws a RankException and we want a consistent ArgumentException for all the IList CopyTo methods.
-            Array.Copy(this, GetLowerBound(0), array!, index, Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Array.Copy(this, GetLowerBound(0), array!, index, Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public void CopyTo(Array array, long index)
@@ -648,7 +649,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 array[i] = value;
             }
@@ -661,22 +662,23 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (startIndex < 0 || startIndex > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (startIndex < 0 || startIndex > array!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index();
             }
 
-            if (count < 0 || startIndex > array!.Length - count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (count < 0 || startIndex > array!.Length - count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count();
             }
 
             for (int i = startIndex; i < startIndex + count; i++)
             {
-                array![i] = value; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                array![i] = value; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
 
+        [return: MaybeNull]
         public static T Find<T>(T[] array, Predicate<T> match)
         {
             if (array == null)
@@ -689,14 +691,14 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
             }
 
-            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
-                if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(array[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     return array[i];
                 }
             }
-            return default!; // TODO-NULLABLE-GENERIC
+            return default!;
         }
 
         public static T[] FindAll<T>(T[] array, Predicate<T> match)
@@ -712,9 +714,9 @@ namespace System
             }
 
             List<T> list = new List<T>();
-            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
-                if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(array[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     list.Add(array[i]);
                 }
@@ -729,7 +731,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return FindIndex(array!, 0, array!.Length, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return FindIndex(array!, 0, array!.Length, match); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int FindIndex<T>(T[] array, int startIndex, Predicate<T> match)
@@ -739,7 +741,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return FindIndex(array!, startIndex, array!.Length - startIndex, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return FindIndex(array!, startIndex, array!.Length - startIndex, match); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int FindIndex<T>(T[] array, int startIndex, int count, Predicate<T> match)
@@ -749,12 +751,12 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (startIndex < 0 || startIndex > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (startIndex < 0 || startIndex > array!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index();
             }
 
-            if (count < 0 || startIndex > array!.Length - count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (count < 0 || startIndex > array!.Length - count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count();
             }
@@ -767,12 +769,13 @@ namespace System
             int endIndex = startIndex + count;
             for (int i = startIndex; i < endIndex; i++)
             {
-                if (match!(array![i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(array![i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     return i;
             }
             return -1;
         }
 
+        [return: MaybeNull]
         public static T FindLast<T>(T[] array, Predicate<T> match)
         {
             if (array == null)
@@ -785,14 +788,14 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
             }
 
-            for (int i = array!.Length - 1; i >= 0; i--) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = array!.Length - 1; i >= 0; i--) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
-                if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(array[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     return array[i];
                 }
             }
-            return default!; // TODO-NULLABLE-GENERIC
+            return default!;
         }
 
         public static int FindLastIndex<T>(T[] array, Predicate<T> match)
@@ -802,7 +805,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return FindLastIndex(array!, array!.Length - 1, array.Length, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return FindLastIndex(array!, array!.Length - 1, array.Length, match); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int FindLastIndex<T>(T[] array, int startIndex, Predicate<T> match)
@@ -812,7 +815,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return FindLastIndex(array!, startIndex, startIndex + 1, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return FindLastIndex(array!, startIndex, startIndex + 1, match); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int FindLastIndex<T>(T[] array, int startIndex, int count, Predicate<T> match)
@@ -827,7 +830,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
             }
 
-            if (array!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Length == 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 // Special case for 0 length List
                 if (startIndex != -1)
@@ -853,7 +856,7 @@ namespace System
             int endIndex = startIndex - count;
             for (int i = startIndex; i > endIndex; i--)
             {
-                if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(array[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     return i;
                 }
@@ -873,9 +876,9 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
             }
 
-            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
-                action!(array[i]); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                action!(array[i]); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
 
@@ -887,7 +890,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            return IndexOf(array!, value, array!.GetLowerBound(0), array.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return IndexOf(array!, value, array!.GetLowerBound(0), array.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Returns the index of the first occurrence of a given value in a range of
@@ -900,7 +903,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             return IndexOf(array, value, startIndex, array.Length - startIndex + lb);
         }
 
@@ -914,7 +917,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
 
             int lb = array.GetLowerBound(0);
@@ -984,7 +987,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return IndexOf(array!, value, 0, array!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return IndexOf(array!, value, 0, array!.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int IndexOf<T>(T[] array, T value, int startIndex)
@@ -994,7 +997,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return IndexOf(array!, value, startIndex, array!.Length - startIndex); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return IndexOf(array!, value, startIndex, array!.Length - startIndex); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
@@ -1004,7 +1007,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if ((uint)startIndex > (uint)array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if ((uint)startIndex > (uint)array!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index();
             }
@@ -1068,7 +1071,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             return LastIndexOf(array, value, array.Length - 1 + lb, array.Length);
         }
 
@@ -1081,7 +1084,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             return LastIndexOf(array, value, startIndex, startIndex + 1 - lb);
         }
 
@@ -1095,7 +1098,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int lb = array!.GetLowerBound(0); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (array.Length == 0)
             {
                 return lb - 1;
@@ -1167,7 +1170,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            return LastIndexOf(array!, value, array!.Length - 1, array.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return LastIndexOf(array!, value, array!.Length - 1, array.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int LastIndexOf<T>(T[] array, T value, int startIndex)
@@ -1177,7 +1180,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
             // if array is empty and startIndex is 0, we need to pass 0 as count
-            return LastIndexOf(array!, value, startIndex, (array!.Length == 0) ? 0 : (startIndex + 1)); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return LastIndexOf(array!, value, startIndex, (array!.Length == 0) ? 0 : (startIndex + 1)); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count)
@@ -1187,7 +1190,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (array!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Length == 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 //
                 // Special case for 0 length List
@@ -1282,7 +1285,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            Reverse(array!, array!.GetLowerBound(0), array.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Reverse(array!, array!.GetLowerBound(0), array.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Reverses the elements in a range of an array. Following a call to this
@@ -1295,7 +1298,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            int lowerBound = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int lowerBound = array!.GetLowerBound(0); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (index < lowerBound)
                 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
             if (length < 0)
@@ -1338,7 +1341,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            Reverse(array!, 0, array!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Reverse(array!, 0, array!.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static void Reverse<T>(T[] array, int index, int length)
@@ -1349,7 +1352,7 @@ namespace System
                 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
             if (length < 0)
                 ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
-            if (array!.Length - index < length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Length - index < length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
 
             if (length <= 1)
@@ -1375,7 +1378,7 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            Sort(array!, null, array!.GetLowerBound(0), array.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort(array!, null, array!.GetLowerBound(0), array.Length, null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Sorts the elements of two arrays based on the keys in the first array.
@@ -1388,7 +1391,7 @@ namespace System
         {
             if (keys == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
-            Sort(keys!, items, keys!.GetLowerBound(0), keys.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort(keys!, items, keys!.GetLowerBound(0), keys.Length, null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Sorts the elements in a section of an array. The sort compares the
@@ -1436,7 +1439,7 @@ namespace System
         {
             if (keys == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
-            Sort(keys!, items, keys!.GetLowerBound(0), keys.Length, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort(keys!, items, keys!.GetLowerBound(0), keys.Length, comparer); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Sorts the elements in a section of an array. The sort compares the
@@ -1462,7 +1465,7 @@ namespace System
         {
             if (keys == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
-            if (keys!.Rank != 1 || (items != null && items.Rank != 1)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (keys!.Rank != 1 || (items != null && items.Rank != 1)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
             int keysLowerBound = keys.GetLowerBound(0);
             if (items != null && keysLowerBound != items.GetLowerBound(0))
@@ -1485,14 +1488,14 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            Sort<T>(array!, 0, array!.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort<T>(array!, 0, array!.Length, null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static void Sort<TKey, TValue>(TKey[] keys, TValue[]? items)
         {
             if (keys == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
-            Sort<TKey, TValue>(keys!, items, 0, keys!.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort<TKey, TValue>(keys!, items, 0, keys!.Length, null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static void Sort<T>(T[] array, int index, int length)
@@ -1509,14 +1512,14 @@ namespace System
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            Sort<T>(array!, 0, array!.Length, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort<T>(array!, 0, array!.Length, comparer); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static void Sort<TKey, TValue>(TKey[] keys, TValue[]? items, System.Collections.Generic.IComparer<TKey>? comparer)
         {
             if (keys == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
-            Sort<TKey, TValue>(keys!, items, 0, keys!.Length, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Sort<TKey, TValue>(keys!, items, 0, keys!.Length, comparer); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static void Sort<T>(T[] array, int index, int length, System.Collections.Generic.IComparer<T>? comparer)
@@ -1527,7 +1530,7 @@ namespace System
                 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
             if (length < 0)
                 ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
-            if (array!.Length - index < length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Length - index < length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
 
             if (length > 1)
@@ -1554,7 +1557,7 @@ namespace System
                 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
             if (length < 0)
                 ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
-            if (keys!.Length - index < length || (items != null && index > items.Length - length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (keys!.Length - index < length || (items != null && index > items.Length - length)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
 
             if (length > 1)
@@ -1591,7 +1594,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison);
             }
 
-            ArraySortHelper<T>.Sort(array!, 0, array!.Length, comparison!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ArraySortHelper<T>.Sort(array!, 0, array!.Length, comparison!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static bool TrueForAll<T>(T[] array, Predicate<T> match)
@@ -1606,9 +1609,9 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
             }
 
-            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
-                if (!match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (!match!(array[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     return false;
                 }
index 8098d22..0f6e05f 100644 (file)
@@ -43,7 +43,7 @@ namespace System
 
             _array = array;
             _offset = 0;
-            _count = array!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            _count = array!.Length; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public ArraySegment(T[] array, int offset, int count)
@@ -323,7 +323,7 @@ namespace System
                 Debug.Assert(arraySegment.Array != null);
                 Debug.Assert(arraySegment.Offset >= 0);
                 Debug.Assert(arraySegment.Count >= 0);
-                Debug.Assert(arraySegment.Offset + arraySegment.Count <= arraySegment.Array!.Length); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34792
+                Debug.Assert(arraySegment.Offset + arraySegment.Count <= arraySegment.Array!.Length); // TODO-NULLABLE: Manually-implemented property (https://github.com/dotnet/roslyn/issues/34792)
 
                 _array = arraySegment.Array;
                 _start = arraySegment.Offset;
index 129c009..f6f6b98 100644 (file)
@@ -236,7 +236,7 @@ namespace System
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
             if (startIndex > value.Length - sizeof(short))
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
@@ -257,7 +257,7 @@ namespace System
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
             if (startIndex > value.Length - sizeof(int))
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
@@ -278,7 +278,7 @@ namespace System
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
             if (startIndex > value.Length - sizeof(long))
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
@@ -363,11 +363,11 @@ namespace System
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            if (startIndex < 0 || startIndex >= value!.Length && startIndex > 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (startIndex < 0 || startIndex >= value!.Length && startIndex > 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
             if (length < 0)
                 throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_GenericPositive);
-            if (startIndex > value!.Length - length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (startIndex > value!.Length - length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
 
             if (length == 0)
@@ -409,7 +409,7 @@ namespace System
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            return ToString(value!, 0, value!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return ToString(value!, 0, value!.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Converts an array of bytes into a String.  
@@ -417,7 +417,7 @@ namespace System
         {
             if (value == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
-            return ToString(value!, startIndex, value!.Length - startIndex); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return ToString(value!, startIndex, value!.Length - startIndex); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         /*==================================ToBoolean===================================
@@ -435,7 +435,7 @@ namespace System
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
             if (startIndex < 0)
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
-            if (startIndex > value!.Length - 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (startIndex > value!.Length - 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); // differs from other overloads, which throw base ArgumentException
 
             return value[startIndex] != 0;
index 3adf3b0..1e77538 100644 (file)
@@ -54,7 +54,7 @@ namespace System
             _str = null;
         }
 
-        object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        object? IEnumerator.Current
         {
             get { return Current; }
         }
index c5f3abd..ba4a323 100644 (file)
@@ -295,7 +295,7 @@ namespace System.Collections
             else
             {
                 for (int i = 0; i < _size; i++)
-                    if ((_items[i] != null) && (_items[i]!.Equals(item))) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                    if ((_items[i] != null) && (_items[i]!.Equals(item))) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                         return true;
                 return false;
             }
@@ -969,7 +969,7 @@ namespace System.Collections
                 else
                 {
                     for (int i = startIndex; i < endIndex; i++)
-                        if (_list[i] != null && _list[i]!.Equals(value)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        if (_list[i] != null && _list[i]!.Equals(value)) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                             return i;
                     return -1;
                 }
@@ -1040,7 +1040,7 @@ namespace System.Collections
                 else
                 {
                     for (int i = startIndex; i >= endIndex; i--)
-                        if (_list[i] != null && _list[i]!.Equals(value)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        if (_list[i] != null && _list[i]!.Equals(value)) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                             return i;
                     return -1;
                 }
@@ -2521,7 +2521,7 @@ namespace System.Collections
                 else
                 {
                     for (int i = 0; i < _baseSize; i++)
-                        if (_baseList[_baseIndex + i] != null && _baseList[_baseIndex + i]!.Equals(item)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        if (_baseList[_baseIndex + i] != null && _baseList[_baseIndex + i]!.Equals(item)) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                             return true;
                     return false;
                 }
index f80f4d1..e62e372 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Collections.Concurrent
@@ -99,7 +100,7 @@ namespace System.Collections.Concurrent
 
             // Initialize the segment and add all of the data to it.
             _tail = _head = new ConcurrentQueueSegment<T>(length);
-            foreach (T item in collection!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            foreach (T item in collection!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 Enqueue(item);
             }
@@ -146,7 +147,7 @@ namespace System.Collections.Concurrent
 
             // Otherwise, fall back to the slower path that first copies the contents
             // to an array, and then uses that array's non-generic CopyTo to do the copy.
-            ToArray().CopyTo(array!, index); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ToArray().CopyTo(array!, index); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         /// <summary>
@@ -163,7 +164,7 @@ namespace System.Collections.Concurrent
         /// cref="ICollection"/>. This property is not supported.
         /// </summary>
         /// <exception cref="NotSupportedException">The SyncRoot property is not supported.</exception>
-        object ICollection.SyncRoot { get { ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); return default!; } } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+        object ICollection.SyncRoot { get { ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); return default!; } } // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
         /// <summary>Returns an enumerator that iterates through a collection.</summary>
         /// <returns>An <see cref="IEnumerator"/> that can be used to iterate through the collection.</returns>
@@ -461,7 +462,7 @@ namespace System.Collections.Concurrent
 
             // Get the number of items to be enumerated
             long count = GetCount(head, headHead, tail, tailTail);
-            if (index > array!.Length - count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (index > array!.Length - count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
             }
@@ -678,12 +679,12 @@ namespace System.Collections.Concurrent
         /// true if an element was removed and returned from the beginning of the
         /// <see cref="ConcurrentQueue{T}"/> successfully; otherwise, false.
         /// </returns>
-        public bool TryDequeue(out T result) => // TODO-GENERIC-NULLABLE
+        public bool TryDequeue([MaybeNullWhen(false)] out T result) =>
             _head.TryDequeue(out result) || // fast-path that operates just on the head segment
             TryDequeueSlow(out result); // slow path that needs to fix up segments
 
         /// <summary>Tries to dequeue an item, removing empty segments as needed.</summary>
-        private bool TryDequeueSlow(out T item)
+        private bool TryDequeueSlow([MaybeNullWhen(false)] out T item)
         {
             while (true)
             {
@@ -701,7 +702,7 @@ namespace System.Collections.Concurrent
                 // check and this check, another item could have arrived).
                 if (head._nextSegment == null)
                 {
-                    item = default!; // TODO-NULLABLE-GENERIC
+                    item = default!;
                     return false;
                 }
 
@@ -742,13 +743,13 @@ namespace System.Collections.Concurrent
         /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
         /// property is recommended rather than peeking.
         /// </remarks>
-        public bool TryPeek(out T result) => TryPeek(out result, resultUsed: true); // TODO-GENERIC-NULLABLE
+        public bool TryPeek([MaybeNullWhen(false)] out T result) => TryPeek(out result, resultUsed: true);
 
         /// <summary>Attempts to retrieve the value for the first element in the queue.</summary>
         /// <param name="result">The value of the first element, if found.</param>
         /// <param name="resultUsed">true if the result is needed; otherwise false if only the true/false outcome is needed.</param>
         /// <returns>true if an element was found; otherwise, false.</returns>
-        private bool TryPeek(out T result, bool resultUsed)
+        private bool TryPeek([MaybeNullWhen(false)] out T result, bool resultUsed)
         {
             // Starting with the head segment, look through all of the segments
             // for the first one we can find that's not empty.
@@ -795,7 +796,7 @@ namespace System.Collections.Concurrent
                 // and we'll traverse to that segment.
             }
 
-            result = default!; // TODO-NULLABLE-GENERIC
+            result = default!;
             return false;
         }
 
index c120d77..fcf0539 100644 (file)
@@ -4,6 +4,7 @@
 
 #nullable enable
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Threading;
 
@@ -127,7 +128,7 @@ namespace System.Collections.Concurrent
         }
 
         /// <summary>Tries to dequeue an element from the queue.</summary>
-        public bool TryDequeue(out T item) // TODO-NULLABLE-GENERIC
+        public bool TryDequeue([MaybeNullWhen(false)] out T item)
         {
             Slot[] slots = _slots;
             
@@ -165,7 +166,7 @@ namespace System.Collections.Concurrent
                             // If we're preserving, though, we don't zero out the slot, as we need it for
                             // enumerations, peeking, ToArray, etc.  And we don't update the sequence number,
                             // so that an enqueuer will see it as full and be forced to move to a new segment.
-                            slots[slotsIndex].Item = default!; // TODO-NULLABLE-GENERIC
+                            slots[slotsIndex].Item = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                             Volatile.Write(ref slots[slotsIndex].SequenceNumber, currentHead + slots.Length);
                         }
                         return true;
@@ -184,7 +185,7 @@ namespace System.Collections.Concurrent
                     int currentTail = Volatile.Read(ref _headAndTail.Tail);
                     if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
                     {
-                        item = default!; // TODO-NULLABLE-GENERIC
+                        item = default!;
                         return false;
                     }
 
@@ -199,7 +200,7 @@ namespace System.Collections.Concurrent
         }
 
         /// <summary>Tries to peek at an element from the queue, without removing it.</summary>
-        public bool TryPeek(out T result, bool resultUsed) // TODO-NULLABLE-GENERIC
+        public bool TryPeek([MaybeNullWhen(false)] out T result, bool resultUsed)
         {
             if (resultUsed)
             {
@@ -229,7 +230,7 @@ namespace System.Collections.Concurrent
                 int diff = sequenceNumber - (currentHead + 1);
                 if (diff == 0)
                 {
-                    result = resultUsed ? slots[slotsIndex].Item : default!; // TODO-NULLABLE-GENERIC
+                    result = resultUsed ? slots[slotsIndex].Item : default!;
                     return true;
                 }
                 else if (diff < 0)
@@ -245,7 +246,7 @@ namespace System.Collections.Concurrent
                     int currentTail = Volatile.Read(ref _headAndTail.Tail);
                     if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
                     {
-                        result = default!; // TODO-NULLABLE-GENERIC
+                        result = default!;
                         return false;
                     }
 
@@ -322,7 +323,7 @@ namespace System.Collections.Concurrent
         internal struct Slot
         {
             /// <summary>The item.</summary>
-            public T Item; // SOS's ThreadPool command depends on this being at the beginning of the struct when T is a reference type
+            [AllowNull, MaybeNull] public T Item; // SOS's ThreadPool command depends on this being at the beginning of the struct when T is a reference type
             /// <summary>The sequence number for this slot, used to synchronize between enqueuers and dequeuers.</summary>
             public int SequenceNumber;
         }
index 3f77483..e33c840 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Collections.Concurrent
 {
@@ -58,7 +59,7 @@ namespace System.Collections.Concurrent
         /// unspecified.
         /// </param>
         /// <returns>true if an object was removed and returned successfully; otherwise, false.</returns>
-        bool TryTake(out T item); // TODO-NULLABLE-GENERIC
+        bool TryTake([MaybeNullWhen(false)] out T item);
 
         /// <summary>
         /// Copies the elements contained in the <see cref="IProducerConsumerCollection{T}"/> to a new array.
index 084ecdf..2ec14db 100644 (file)
@@ -14,7 +14,7 @@
 ===========================================================*/
 
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Collections.Generic
 {
@@ -38,6 +38,7 @@ namespace System.Collections.Generic
             return result;
         }
 
+        [DoesNotReturn]
         internal static void ThrowOrIgnoreBadComparer(object? comparer)
         {
             throw new ArgumentException(SR.Format(SR.Arg_BogusIComparer, comparer));
index 28cb0af..80187be 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.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
@@ -21,7 +22,7 @@ namespace System.Collections.Generic
             return new ComparisonComparer<T>(comparison);
         }
 
-        public abstract int Compare(T x, T y); // TODO-NULLABLE-GENERIC: x and y must be marked as nullable
+        public abstract int Compare([AllowNull] T x, [AllowNull] T y);
 
         int IComparer.Compare(object? x, object? y)
         {
@@ -58,7 +59,7 @@ namespace System.Collections.Generic
     // Needs to be public to support binary serialization compatibility
     public sealed partial class GenericComparer<T> : Comparer<T> where T : IComparable<T>
     {
-        public override int Compare(T x, T y) // TODO-NULLABLE-GENERIC: x and y must be marked as nullable
+        public override int Compare([AllowNull] T x, [AllowNull] T y)
         {
             if (x != null)
             {
@@ -106,7 +107,7 @@ namespace System.Collections.Generic
     // Needs to be public to support binary serialization compatibility
     public sealed partial class ObjectComparer<T> : Comparer<T>
     {
-        public override int Compare(T x, T y) // TODO-NULLABLE-GENERIC: x and y must be marked as nullable
+        public override int Compare([AllowNull] T x, [AllowNull] T y)
         {
             return System.Collections.Comparer.Default.Compare(x, y);
         }
index 296a607..d79924c 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
@@ -99,7 +100,7 @@ namespace System.Collections.Generic
             // avoid the enumerator allocation and overhead by looping through the entries array directly.
             // We only do this when dictionary is Dictionary<TKey,TValue> and not a subclass, to maintain
             // back-compat with subclasses that may have overridden the enumerator behavior.
-            if (dictionary!.GetType() == typeof(Dictionary<TKey, TValue>)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (dictionary!.GetType() == typeof(Dictionary<TKey, TValue>)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 Dictionary<TKey, TValue> d = (Dictionary<TKey, TValue>)dictionary;
                 int count = d._count;
@@ -130,7 +131,7 @@ namespace System.Collections.Generic
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
             }
 
-            foreach (KeyValuePair<TKey, TValue> pair in collection!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            foreach (KeyValuePair<TKey, TValue> pair in collection!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 Add(pair.Key, pair.Value);
             }
@@ -218,7 +219,7 @@ namespace System.Collections.Generic
                 int i = FindEntry(key);
                 if (i >= 0) return _entries![i].value;
                 ThrowHelper.ThrowKeyNotFoundException(key);
-                return default!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 (annotating ThrowHelper removes this return statement).
+                return default!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             set
             {
@@ -289,7 +290,7 @@ namespace System.Collections.Generic
             }
             else
             {
-                if (default(TValue)! != null) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/34757
+                if (default(TValue)! != null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 {
                     // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
                     for (int i = 0; i < _count; i++)
@@ -319,7 +320,7 @@ namespace System.Collections.Generic
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if ((uint)index > (uint)array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if ((uint)index > (uint)array!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
             }
@@ -353,7 +354,7 @@ namespace System.Collections.Generic
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info);
             }
 
-            info!.AddValue(VersionName, _version); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            info!.AddValue(VersionName, _version); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             info.AddValue(ComparerName, _comparer ?? EqualityComparer<TKey>.Default, typeof(IEqualityComparer<TKey>));
             info.AddValue(HashSizeName, _buckets == null ? 0 : _buckets.Length); // This is the length of the bucket array
 
@@ -382,10 +383,10 @@ namespace System.Collections.Generic
                 IEqualityComparer<TKey>? comparer = _comparer;
                 if (comparer == null)
                 {
-                    uint hashCode = (uint)key!.GetHashCode(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    uint hashCode = (uint)key!.GetHashCode(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     // Value in _buckets is 1-based
                     i = buckets[hashCode % (uint)buckets.Length] - 1;
-                    if (default(TKey)! != null) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/34757
+                    if (default(TKey)! != null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                     {
                         // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
                         do
@@ -485,21 +486,22 @@ namespace System.Collections.Generic
             {
                 Initialize(0);
             }
+            Debug.Assert(_buckets != null);
 
             Entry[]? entries = _entries;
             Debug.Assert(entries != null, "expected entries to be non-null");
 
             IEqualityComparer<TKey>? comparer = _comparer;
-            uint hashCode = (uint)((comparer == null) ? key!.GetHashCode() : comparer.GetHashCode(key)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            uint hashCode = (uint)((comparer == null) ? key!.GetHashCode() : comparer.GetHashCode(key)); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             int collisionCount = 0;
-            ref int bucket = ref _buckets![hashCode % (uint)_buckets.Length]; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 (Initialize inits sets _buckets to non null)
+            ref int bucket = ref _buckets[hashCode % (uint)_buckets.Length];
             // Value in _buckets is 1-based
             int i = bucket - 1;
 
             if (comparer == null)
             {
-                if (default(TKey)! != null) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/34757
+                if (default(TKey)! != null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 {
                     // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
                     do
@@ -660,7 +662,7 @@ namespace System.Collections.Generic
             _version++;
 
             // Value types never rehash
-            if (default(TKey)! == null && collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(TKey)! == null && collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 // If we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing
                 // i.e. EqualityComparer<string>.Default.
@@ -698,7 +700,7 @@ namespace System.Collections.Generic
                     ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingKeys);
                 }
 
-                for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     if (array[i].Key == null)
                     {
@@ -722,7 +724,7 @@ namespace System.Collections.Generic
         private void Resize(int newSize, bool forceNewHashCodes)
         {
             // Value types never rehash
-            Debug.Assert(!forceNewHashCodes || default(TKey)! == null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            Debug.Assert(!forceNewHashCodes || default(TKey)! == null); // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             Debug.Assert(_entries != null, "_entries should be non-null");
             Debug.Assert(newSize >= _entries.Length);
 
@@ -732,7 +734,7 @@ namespace System.Collections.Generic
             int count = _count;
             Array.Copy(_entries, 0, entries, 0, count);
 
-            if (default(TKey)! == null && forceNewHashCodes) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(TKey)! == null && forceNewHashCodes) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 for (int i = 0; i < count; i++)
                 {
@@ -776,7 +778,7 @@ namespace System.Collections.Generic
             if (buckets != null)
             {
                 Debug.Assert(entries != null, "entries should be non-null");
-                uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key!.GetHashCode()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key!.GetHashCode()); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 uint bucket = hashCode % (uint)buckets.Length;
                 int last = -1;
                 // Value in buckets is 1-based
@@ -803,11 +805,11 @@ namespace System.Collections.Generic
 
                         if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>())
                         {
-                            entry.key = default!; // TODO-NULLABLE-GENERIC
+                            entry.key = default!;
                         }
                         if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>())
                         {
-                            entry.value = default!; // TODO-NULLABLE-GENERIC
+                            entry.value = default!;
                         }
                         _freeList = i;
                         _freeCount++;
@@ -831,7 +833,7 @@ namespace System.Collections.Generic
         // This overload is a copy of the overload Remove(TKey key) with one additional
         // statement to copy the value for entry being removed into the output parameter.
         // Code has been intentionally duplicated for performance reasons.
-        public bool Remove(TKey key, out TValue value) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/26761
+        public bool Remove(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
             if (key == null)
             {
@@ -844,7 +846,7 @@ namespace System.Collections.Generic
             if (buckets != null)
             {
                 Debug.Assert(entries != null, "entries should be non-null");
-                uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key!.GetHashCode()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key!.GetHashCode()); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 uint bucket = hashCode % (uint)buckets.Length;
                 int last = -1;
                 // Value in buckets is 1-based
@@ -873,11 +875,11 @@ namespace System.Collections.Generic
 
                         if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>())
                         {
-                            entry.key = default!; // TODO-NULLABLE-GENERIC
+                            entry.key = default!;
                         }
                         if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>())
                         {
-                            entry.value = default!; // TODO-NULLABLE-GENERIC
+                            entry.value = default!;
                         }
                         _freeList = i;
                         _freeCount++;
@@ -895,11 +897,11 @@ namespace System.Collections.Generic
                     collisionCount++;
                 }
             }
-            value = default!; // TODO-NULLABLE-GENERIC
+            value = default!;
             return false;
         }
 
-        public bool TryGetValue(TKey key, out TValue value) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/26761
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
             int i = FindEntry(key);
             if (i >= 0)
@@ -907,7 +909,7 @@ namespace System.Collections.Generic
                 value = _entries![i].value;
                 return true;
             }
-            value = default!; // TODO-NULLABLE-GENERIC
+            value = default!;
             return false;
         }
 
@@ -923,7 +925,7 @@ namespace System.Collections.Generic
         {
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
             if (array.GetLowerBound(0) != 0)
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
@@ -963,7 +965,7 @@ namespace System.Collections.Generic
                     {
                         if (entries![i].next >= -1)
                         {
-                            objects![index++] = new KeyValuePair<TKey, TValue>(entries[i].key, entries[i].value); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            objects![index++] = new KeyValuePair<TKey, TValue>(entries[i].key, entries[i].value); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                         }
                     }
                 }
@@ -1063,7 +1065,8 @@ namespace System.Collections.Generic
 
         ICollection IDictionary.Values => (ICollection)Values;
 
-        object? IDictionary.this[object key] // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+        [DisallowNull]
+        object? IDictionary.this[object key]
         {
             get
             {
@@ -1087,7 +1090,7 @@ namespace System.Collections.Generic
 
                 try
                 {
-                    TKey tempKey = (TKey)key!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    TKey tempKey = (TKey)key!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     try
                     {
                         this[tempKey] = (TValue)value!;
@@ -1123,7 +1126,7 @@ namespace System.Collections.Generic
 
             try
             {
-                TKey tempKey = (TKey)key!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                TKey tempKey = (TKey)key!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
                 try
                 {
@@ -1213,7 +1216,7 @@ namespace System.Collections.Generic
             {
             }
 
-            object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+            object? IEnumerator.Current
             {
                 get
                 {
@@ -1296,7 +1299,7 @@ namespace System.Collections.Generic
                 {
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
                 }
-                _dictionary = dictionary!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                _dictionary = dictionary!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             public Enumerator GetEnumerator()
@@ -1309,12 +1312,12 @@ namespace System.Collections.Generic
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
                 }
 
-                if (index < 0 || index > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                if (index < 0 || index > array!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
                 }
 
-                if (array!.Length - index < _dictionary.Count) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                if (array!.Length - index < _dictionary.Count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
                 }
@@ -1356,7 +1359,7 @@ namespace System.Collections.Generic
             {
                 if (array == null)
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-                if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
                 if (array.GetLowerBound(0) != 0)
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
@@ -1383,7 +1386,7 @@ namespace System.Collections.Generic
                     {
                         for (int i = 0; i < count; i++)
                         {
-                            if (entries![i].next >= -1) objects![index++] = entries[i].key; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 (objects)
+                            if (entries![i].next >= -1) objects![index++] = entries[i].key; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                         }
                     }
                     catch (ArrayTypeMismatchException)
@@ -1402,14 +1405,14 @@ namespace System.Collections.Generic
                 private readonly Dictionary<TKey, TValue> _dictionary;
                 private int _index;
                 private readonly int _version;
-                private TKey _currentKey;
+                [AllowNull, MaybeNull] private TKey _currentKey;
 
                 internal Enumerator(Dictionary<TKey, TValue> dictionary)
                 {
                     _dictionary = dictionary;
                     _version = dictionary._version;
                     _index = 0;
-                    _currentKey = default!; // TODO-NULLABLE-GENERIC
+                    _currentKey = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
 
                 public void Dispose()
@@ -1435,13 +1438,13 @@ namespace System.Collections.Generic
                     }
 
                     _index = _dictionary._count + 1;
-                    _currentKey = default!; // TODO-NULLABLE-GENERIC
+                    _currentKey = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     return false;
                 }
 
-                public TKey Current => _currentKey;
+                public TKey Current => _currentKey!;
 
-                object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+                object? IEnumerator.Current
                 {
                     get
                     {
@@ -1462,7 +1465,7 @@ namespace System.Collections.Generic
                     }
 
                     _index = 0;
-                    _currentKey = default!; // TODO-NULLABLE-GENERIC
+                    _currentKey = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
             }
         }
@@ -1479,7 +1482,7 @@ namespace System.Collections.Generic
                 {
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
                 }
-                _dictionary = dictionary!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                _dictionary = dictionary!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             public Enumerator GetEnumerator()
@@ -1492,7 +1495,7 @@ namespace System.Collections.Generic
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
                 }
 
-                if ((uint)index > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if ((uint)index > array!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
                 }
@@ -1539,7 +1542,7 @@ namespace System.Collections.Generic
             {
                 if (array == null)
                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-                if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
                 if (array.GetLowerBound(0) != 0)
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
@@ -1566,7 +1569,7 @@ namespace System.Collections.Generic
                     {
                         for (int i = 0; i < count; i++)
                         {
-                            if (entries![i].next >= -1) objects![index++] = entries[i].value!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                            if (entries![i].next >= -1) objects![index++] = entries[i].value!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                         }
                     }
                     catch (ArrayTypeMismatchException)
@@ -1585,14 +1588,14 @@ namespace System.Collections.Generic
                 private readonly Dictionary<TKey, TValue> _dictionary;
                 private int _index;
                 private readonly int _version;
-                private TValue _currentValue;
+                [AllowNull, MaybeNull] private TValue _currentValue;
 
                 internal Enumerator(Dictionary<TKey, TValue> dictionary)
                 {
                     _dictionary = dictionary;
                     _version = dictionary._version;
                     _index = 0;
-                    _currentValue = default!; // TODO-NULLABLE-GENERIC
+                    _currentValue = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
 
                 public void Dispose()
@@ -1617,11 +1620,11 @@ namespace System.Collections.Generic
                         }
                     }
                     _index = _dictionary._count + 1;
-                    _currentValue = default!; // TODO-NULLABLE-GENERIC
+                    _currentValue = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     return false;
                 }
 
-                public TValue Current => _currentValue;
+                public TValue Current => _currentValue!;
 
                 object? IEnumerator.Current
                 {
@@ -1643,7 +1646,7 @@ namespace System.Collections.Generic
                         ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
                     }
                     _index = 0;
-                    _currentValue = default!; // TODO-NULLABLE-GENERIC
+                    _currentValue = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
             }
         }
index b6040ad..86a4e2a 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.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
@@ -13,10 +14,10 @@ namespace System.Collections.Generic
     {
         // public static EqualityComparer<T> Default is runtime-specific
 
-        public abstract bool Equals(T x, T y);
-        public abstract int GetHashCode(T obj); // TODO-NULLABLE-GENERIC: Shouldn't accept nulls.
+        public abstract bool Equals([AllowNull] T x, [AllowNull] T y);
+        public abstract int GetHashCode([DisallowNull] T obj);
 
-#pragma warning disable CS8617 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/30958
+#pragma warning disable CS8617 // TODO-NULLABLE: Covariant parameter types (https://github.com/dotnet/roslyn/issues/30958)
         int IEqualityComparer.GetHashCode(object? obj)
 #pragma warning restore CS8617
         {
@@ -44,7 +45,7 @@ namespace System.Collections.Generic
     public sealed partial class GenericEqualityComparer<T> : EqualityComparer<T> where T : IEquatable<T>
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public override bool Equals(T x, T y)
+        public override bool Equals([AllowNull] T x, [AllowNull] T y)
         {
             if (x != null)
             {
@@ -56,7 +57,7 @@ namespace System.Collections.Generic
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0;
+        public override int GetHashCode([DisallowNull] T obj) => obj?.GetHashCode() ?? 0;
 
         // Equals method for the comparer itself.
         // If in the future this type is made sealed, change the is check to obj != null && GetType() == obj.GetType().
@@ -102,7 +103,7 @@ namespace System.Collections.Generic
     public sealed partial class ObjectEqualityComparer<T> : EqualityComparer<T>
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public override bool Equals(T x, T y)
+        public override bool Equals([AllowNull] T x, [AllowNull] T y)
         {
             if (x != null)
             {
@@ -114,7 +115,7 @@ namespace System.Collections.Generic
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0;
+        public override int GetHashCode([DisallowNull] T obj) => obj?.GetHashCode() ?? 0;
 
         // Equals method for the comparer itself.
         public override bool Equals(object? obj) =>
index 200ce17..064aa31 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Collections.Generic
 {
@@ -15,6 +16,6 @@ namespace System.Collections.Generic
         // value less than zero if x is less than y, zero if x is equal to y, or a
         // value greater than zero if x is greater than y.
         // 
-        int Compare(T x, T y); // TODO-NULLABLE-GENERIC: must work with nulls
+        int Compare([AllowNull] T x, [AllowNull] T y);
     }
 }
index 75bc1bc..a93ec25 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Collections.Generic
 {
@@ -45,6 +46,6 @@ namespace System.Collections.Generic
         //
         bool Remove(TKey key);
 
-        bool TryGetValue(TKey key, out TValue value); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value);
     }
 }
index 54925e9..025d693 100644 (file)
@@ -2,6 +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.Diagnostics.CodeAnalysis;
+
 namespace System.Collections.Generic
 {
     // The generic IEqualityComparer interface implements methods to if check two objects are equal
@@ -9,8 +11,8 @@ namespace System.Collections.Generic
     // It is use in Dictionary class.  
     public interface IEqualityComparer<in T>
     {
-        bool Equals(T x, T y);
-        int GetHashCode(T obj); // TODO-NULLABLE-GENERIC: This generally doesn't accept nulls.
+        bool Equals([AllowNull] T x, [AllowNull] T y);
+        int GetHashCode([DisallowNull] T obj);
     }
 }
 
index 1d57383..48e9602 100644 (file)
@@ -2,7 +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.
 
-using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Collections.Generic
 {
@@ -10,7 +10,7 @@ namespace System.Collections.Generic
     public interface IReadOnlyDictionary<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, TValue>> where TKey : object
     {
         bool ContainsKey(TKey key);
-        bool TryGetValue(TKey key, out TValue value); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value);
 
         TValue this[TKey key] { get; }
         IEnumerable<TKey> Keys { get; }
index 760220a..4a27224 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.ObjectModel;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Threading;
 
@@ -170,10 +171,10 @@ namespace System.Collections.Generic
         {
             // Non-null values are fine.  Only accept nulls if T is a class or Nullable<U>.
             // Note that default(T) is not equal to null for value types except when T is Nullable<U>. 
-            return ((value is T) || (value == null && default(T)! == null)); // https://github.com/dotnet/roslyn/issues/34757
+            return ((value is T) || (value == null && default(T)! == null)); // default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
         }
 
-        object? IList.this[int index] // TODO-NULLABLE-GENERIC: nullability is the same as of T
+        object? IList.this[int index]
         {
             get
             {
@@ -225,7 +226,7 @@ namespace System.Collections.Generic
             _items[size] = item;
         }
 
-        int IList.Add(object? item) // TODO-NULLABLE-GENERIC: nullable if default(T) can be null
+        int IList.Add(object? item)
         {
             ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
 
@@ -345,7 +346,7 @@ namespace System.Collections.Generic
             List<TOutput> list = new List<TOutput>(_size);
             for (int i = 0; i < _size; i++)
             {
-                list._items[i] = converter!(_items[i]); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                list._items[i] = converter!(_items[i]); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             list._size = _size;
             return list;
@@ -418,6 +419,7 @@ namespace System.Collections.Generic
         public bool Exists(Predicate<T> match)
             => FindIndex(match) != -1;
 
+        [return: MaybeNull]
         public T Find(Predicate<T> match)
         {
             if (match == null)
@@ -432,7 +434,7 @@ namespace System.Collections.Generic
                     return _items[i];
                 }
             }
-            return default!; // TODO-NULLABLE-GENERIC: return value is nullable when T can be nullable
+            return default!;
         }
 
         public List<T> FindAll(Predicate<T> match)
@@ -445,7 +447,7 @@ namespace System.Collections.Generic
             List<T> list = new List<T>();
             for (int i = 0; i < _size; i++)
             {
-                if (match!(_items[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(_items[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     list.Add(_items[i]);
                 }
@@ -484,6 +486,7 @@ namespace System.Collections.Generic
             return -1;
         }
 
+        [return: MaybeNull]
         public T FindLast(Predicate<T> match)
         {
             if (match == null)
@@ -498,7 +501,7 @@ namespace System.Collections.Generic
                     return _items[i];
                 }
             }
-            return default!; // TODO-NULLABLE-GENERIC: return value is nullable when T can be nullable
+            return default!;
         }
 
         public int FindLastIndex(Predicate<T> match)
@@ -540,7 +543,7 @@ namespace System.Collections.Generic
             int endIndex = startIndex - count;
             for (int i = startIndex; i > endIndex; i--)
             {
-                if (match!(_items[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (match!(_items[i])) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     return i;
                 }
@@ -619,7 +622,7 @@ namespace System.Collections.Generic
         public int IndexOf(T item)
             => Array.IndexOf(_items, item, 0, _size);
 
-        int IList.IndexOf(object? item) // TODO-NULLABLE-GENERIC: nullability == nullability(T)
+        int IList.IndexOf(object? item)
         {
             if (IsCompatibleObject(item))
             {
@@ -685,7 +688,7 @@ namespace System.Collections.Generic
             _version++;
         }
 
-        void IList.Insert(int index, object? item) // TODO-NULLABLE-GENERIC: nullable when T can be null
+        void IList.Insert(int index, object? item)
         {
             ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
 
@@ -744,7 +747,7 @@ namespace System.Collections.Generic
             }
             else
             {
-                using (IEnumerator<T> en = collection!.GetEnumerator()) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                using (IEnumerator<T> en = collection!.GetEnumerator()) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     while (en.MoveNext())
                     {
@@ -844,7 +847,7 @@ namespace System.Collections.Generic
             return false;
         }
 
-        void IList.Remove(object? item) // TODO-NULLABLE-GENERIC: nullable when T can be null
+        void IList.Remove(object? item)
         {
             if (IsCompatibleObject(item))
             {
@@ -864,7 +867,7 @@ namespace System.Collections.Generic
             int freeIndex = 0;   // the first free slot in items array
 
             // Find the first item which needs to be removed.
-            while (freeIndex < _size && !match!(_items[freeIndex])) freeIndex++; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            while (freeIndex < _size && !match!(_items[freeIndex])) freeIndex++; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (freeIndex >= _size) return 0;
 
             int current = freeIndex + 1;
@@ -1023,7 +1026,7 @@ namespace System.Collections.Generic
 
             if (_size > 1)
             {
-                ArraySortHelper<T>.Sort(_items, 0, _size, comparison!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                ArraySortHelper<T>.Sort(_items, 0, _size, comparison!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             _version++;
         }
@@ -1082,14 +1085,14 @@ namespace System.Collections.Generic
             private readonly List<T> _list;
             private int _index;
             private readonly int _version;
-            private T _current; // TODO-NULLABLE-GENERIC: nullable when T can be null
+            [AllowNull, MaybeNull] private T _current;
 
             internal Enumerator(List<T> list)
             {
                 _list = list;
                 _index = 0;
                 _version = list._version;
-                _current = default!;
+                _current = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
             }
 
             public void Dispose()
@@ -1117,11 +1120,11 @@ namespace System.Collections.Generic
                 }
 
                 _index = _list._size + 1;
-                _current = default!;
+                _current = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 return false;
             }
 
-            public T Current => _current;
+            public T Current => _current!;
 
             object? IEnumerator.Current
             {
@@ -1143,7 +1146,7 @@ namespace System.Collections.Generic
                 }
 
                 _index = 0;
-                _current = default!;
+                _current = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
             }
         }
     }
index 26ffdf7..f042a6b 100644 (file)
@@ -28,9 +28,7 @@ namespace System.Collections.Generic
         public void GetObjectData(SerializationInfo info, StreamingContext context)
         {
             // We are doing this to stay compatible with .NET Framework.
-#pragma warning disable CS8631 // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/35406
             info.SetType(typeof(GenericEqualityComparer<string>));
-#pragma warning restore
         }
     }
 } 
index b3aa57c..64cf029 100644 (file)
@@ -22,7 +22,7 @@ namespace System.Collections
                 if (s_serializationInfoTable == null)
                     Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null);
 
-                return s_serializationInfoTable!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34901
+                return s_serializationInfoTable!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
     }
index 0389563..5512500 100644 (file)
@@ -2,6 +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.Diagnostics.CodeAnalysis;
+
 namespace System.Collections
 {
     // An IDictionary is a possibly unordered set of key-value pairs.
@@ -13,46 +15,36 @@ namespace System.Collections
         // Interfaces are not serializable
         // The Item property provides methods to read and edit entries 
         // in the Dictionary.
-        object? this[object key] // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+        [DisallowNull]
+        object? this[object key]
         {
             get;
             set;
         }
 
         // Returns a collections of the keys in this dictionary.
-        ICollection Keys
-        {
-            get;
-        }
+        ICollection Keys {get; }
 
         // Returns a collections of the values in this dictionary.
-        ICollection Values
-        {
-            get;
-        }
+        ICollection Values { get; }
 
         // Returns whether this dictionary contains a particular key.
-        //
         bool Contains(object key);
 
         // Adds a key-value pair to the dictionary.
-        // 
         void Add(object key, object? value);
 
         // Removes all pairs from the dictionary.
         void Clear();
 
-        bool IsReadOnly
-        { get; }
+        bool IsReadOnly { get; }
 
-        bool IsFixedSize
-        { get; }
+        bool IsFixedSize { get; }
 
         // Returns an IDictionaryEnumerator for this dictionary.
         new IDictionaryEnumerator GetEnumerator();
 
         // Removes a particular key from the dictionary.
-        //
         void Remove(object key);
     }
 }
index 13daac5..b6b5462 100644 (file)
@@ -283,7 +283,7 @@ namespace System.Collections
                 current = null;
             }
 
-#pragma warning disable CS8612 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/30958
+#pragma warning disable CS8612 // TODO-NULLABLE: Covariant parameter types (https://github.com/dotnet/roslyn/issues/30958)
             public object Current
 #pragma warning restore CS8612
             {
index f8c9b87..6cf8438 100644 (file)
@@ -26,7 +26,7 @@ namespace System.Collections.ObjectModel
             {
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
             }
-            items = list!;  // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            items = list!;  // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public int Count
@@ -133,7 +133,7 @@ namespace System.Collections.ObjectModel
                 ThrowHelper.ThrowArgumentOutOfRange_IndexException();
             }
 
-            InsertItemsRange(index, collection!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            InsertItemsRange(index, collection!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public bool Remove(T item)
@@ -201,7 +201,7 @@ namespace System.Collections.ObjectModel
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
             }
 
-            ReplaceItemsRange(index, count, collection!);  // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ReplaceItemsRange(index, count, collection!);  // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public void RemoveAt(int index)
@@ -308,7 +308,7 @@ namespace System.Collections.ObjectModel
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Rank != 1) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
             }
@@ -362,7 +362,7 @@ namespace System.Collections.ObjectModel
                 {
                     for (int i = 0; i < count; i++)
                     {
-                        objects![index++] = items[i];  // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                        objects![index++] = items[i];  // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     }
                 }
                 catch (ArrayTypeMismatchException)
@@ -381,7 +381,7 @@ namespace System.Collections.ObjectModel
 
                 try
                 {
-                    this[index] = (T)value!;  // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    this[index] = (T)value!;
                 }
                 catch (InvalidCastException)
                 {
@@ -424,7 +424,7 @@ namespace System.Collections.ObjectModel
 
             try
             {
-                Add((T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                Add((T)value!);
             }
             catch (InvalidCastException)
             {
@@ -438,7 +438,7 @@ namespace System.Collections.ObjectModel
         {
             if (IsCompatibleObject(value))
             {
-                return Contains((T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return Contains((T)value!);
             }
             return false;
         }
@@ -447,7 +447,7 @@ namespace System.Collections.ObjectModel
         {
             if (IsCompatibleObject(value))
             {
-                return IndexOf((T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return IndexOf((T)value!);
             }
             return -1;
         }
@@ -462,7 +462,7 @@ namespace System.Collections.ObjectModel
 
             try
             {
-                Insert(index, (T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                Insert(index, (T)value!);
             }
             catch (InvalidCastException)
             {
@@ -479,7 +479,7 @@ namespace System.Collections.ObjectModel
 
             if (IsCompatibleObject(value))
             {
-                Remove((T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                Remove((T)value!);
             }
         }
 
index c29d449..69b3424 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Collections.ObjectModel
             {
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
             }
-            this.list = list!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            this.list = list!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public int Count
@@ -127,7 +127,7 @@ namespace System.Collections.ObjectModel
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            if (array!.Rank != 1)  // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (array!.Rank != 1)  // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
             }
@@ -181,7 +181,7 @@ namespace System.Collections.ObjectModel
                 {
                     for (int i = 0; i < count; i++)
                     {
-                        objects![index++] = list[i]; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                        objects![index++] = list[i]; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                     }
                 }
                 catch (ArrayTypeMismatchException)
@@ -232,7 +232,7 @@ namespace System.Collections.ObjectModel
         {
             if (IsCompatibleObject(value))
             {
-                return Contains((T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return Contains((T)value!);
             }
             return false;
         }
@@ -241,7 +241,7 @@ namespace System.Collections.ObjectModel
         {
             if (IsCompatibleObject(value))
             {
-                return IndexOf((T)value!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return IndexOf((T)value!);
             }
             return -1;
         }
index 46192a2..412528c 100644 (file)
@@ -11,6 +11,7 @@ using System.Runtime.InteropServices;
 using System.Runtime.Versioning;
 using System.Security;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System
 {
@@ -311,7 +312,8 @@ namespace System
             return ChangeType(value, conversionType, CultureInfo.CurrentCulture);
         }
 
-        public static object? ChangeType(object? value, Type conversionType, IFormatProvider? provider) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("value")]
+        public static object? ChangeType(object? value, Type conversionType, IFormatProvider? provider)
         {
             if (conversionType is null)
             {
@@ -372,22 +374,31 @@ namespace System
             return ic.ToType(conversionType, provider);
         }
 
+        [DoesNotReturn]
         private static void ThrowCharOverflowException() { throw new OverflowException(SR.Overflow_Char); }
 
+        [DoesNotReturn]
         private static void ThrowByteOverflowException() { throw new OverflowException(SR.Overflow_Byte); }
 
+        [DoesNotReturn]
         private static void ThrowSByteOverflowException() { throw new OverflowException(SR.Overflow_SByte); }
 
+        [DoesNotReturn]
         private static void ThrowInt16OverflowException() { throw new OverflowException(SR.Overflow_Int16); }
 
+        [DoesNotReturn]
         private static void ThrowUInt16OverflowException() { throw new OverflowException(SR.Overflow_UInt16); }
 
+        [DoesNotReturn]
         private static void ThrowInt32OverflowException() { throw new OverflowException(SR.Overflow_Int32); }
 
+        [DoesNotReturn]
         private static void ThrowUInt32OverflowException() { throw new OverflowException(SR.Overflow_UInt32); }
 
+        [DoesNotReturn]
         private static void ThrowInt64OverflowException() { throw new OverflowException(SR.Overflow_Int64); }
 
+        [DoesNotReturn]
         private static void ThrowUInt64OverflowException() { throw new OverflowException(SR.Overflow_UInt64); }
 
         // Conversions to Boolean
@@ -2153,14 +2164,16 @@ namespace System
             return value.ToString(provider);
         }
 
-        public static string? ToString(string? value) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("value")]
+        public static string? ToString(string? value)
         {
             return value;
         }
 
-        public static string? ToString(string? value, IFormatProvider? provider) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("value")]
+        public static string? ToString(string? value, IFormatProvider? provider)
         {
-            return value; // avoid the null check
+            return value;
         }
 
 
index d2cb079..e328726 100644 (file)
@@ -658,7 +658,7 @@ namespace System
         public static DateTimeOffset Parse(string input, IFormatProvider? formatProvider)
         {
             if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
-            return Parse(input!, formatProvider, DateTimeStyles.None); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return Parse(input!, formatProvider, DateTimeStyles.None); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public static DateTimeOffset Parse(string input, IFormatProvider? formatProvider, DateTimeStyles styles)
@@ -689,7 +689,7 @@ namespace System
         {
             if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
             if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
-            return ParseExact(input!, format!, formatProvider, DateTimeStyles.None); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return ParseExact(input!, format!, formatProvider, DateTimeStyles.None); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Constructs a DateTimeOffset from a string. The string must specify a
index 6e6379e..0aef8ad 100644 (file)
@@ -84,7 +84,7 @@ namespace System
             {
                 if (args[i] != null)
                 {
-                    argTypes[i] = args[i]!.GetType(); //TODO-NULLABLE https://github.com/dotnet/csharplang/issues/2388
+                    argTypes[i] = args[i]!.GetType();
                 }
             }
 #endregion
@@ -106,7 +106,7 @@ namespace System
                     continue;
 
                 // Validate the parameters.
-                ParameterInfo[] par = candidates[i]!.GetParametersNoCopy(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                ParameterInfo[] par = candidates[i]!.GetParametersNoCopy(); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
 
 #region Match method by parameter count
                 if (par.Length == 0)
@@ -114,7 +114,7 @@ namespace System
 #region No formal parameters
                     if (args.Length != 0)
                     {
-                        if ((candidates[i]!.CallingConvention & CallingConventions.VarArgs) == 0) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        if ((candidates[i]!.CallingConvention & CallingConventions.VarArgs) == 0) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                             continue;
                     }
 
index 5c4def4..62c3910 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.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
@@ -12,7 +13,9 @@ namespace System
     {
         public virtual object Clone() => MemberwiseClone();
 
-        public static Delegate? Combine(Delegate? a, Delegate? b) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("a")]
+        [return: NotNullIfNotNull("b")]
+        public static Delegate? Combine(Delegate? a, Delegate? b)
         {
             if (a is null)
                 return b;
@@ -20,7 +23,7 @@ namespace System
             return a.CombineImpl(b);
         }
 
-        public static Delegate? Combine(params Delegate?[]? delegates) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static Delegate? Combine(params Delegate?[]? delegates)
         {
             if (delegates == null || delegates.Length == 0)
                 return null;
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
new file mode 100644 (file)
index 0000000..640ff8f
--- /dev/null
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.CodeAnalysis
+{
+    /// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
+    public sealed class AllowNullAttribute : Attribute { }
+
+    /// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
+    public sealed class DisallowNullAttribute : Attribute { }
+
+    /// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
+    public sealed class MaybeNullAttribute : Attribute { }
+
+    /// <summary>Specifies that an output will not be null even if the corresponding type allows it.</summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
+    public sealed class NotNullAttribute : Attribute { }
+
+    /// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
+    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+    public sealed class MaybeNullWhenAttribute : Attribute
+    {
+        /// <summary>Initializes the attribute with the specified return value condition.</summary>
+        /// <param name="returnValue">
+        /// The return value condition. If the method returns this value, the associated parameter may be null.
+        /// </param>
+        public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+
+        /// <summary>Gets the return value condition.</summary>
+        public bool ReturnValue { get; }
+    }
+
+    /// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
+    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+    public sealed class NotNullWhenAttribute : Attribute
+    {
+        /// <summary>Initializes the attribute with the specified return value condition.</summary>
+        /// <param name="returnValue">
+        /// The return value condition. If the method returns this value, the associated parameter will not be null.
+        /// </param>
+        public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+
+        /// <summary>Gets the return value condition.</summary>
+        public bool ReturnValue { get; }
+    }
+
+    /// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
+    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
+    public sealed class NotNullIfNotNullAttribute : Attribute
+    {
+        /// <summary>Initializes the attribute with the associated parameter name.</summary>
+        /// <param name="parameterName">
+        /// The associated parameter name.  The output will be non-null if the argument to the parameter specified is non-null.
+        /// </param>
+        public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;
+
+        /// <summary>Gets the associated parameter name.</summary>
+        public string ParameterName { get; }
+    }
+
+    /// <summary>Applied to a method that will never return under any circumstance.</summary>
+    [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+    public sealed class DoesNotReturnAttribute : Attribute { }
+
+    /// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
+    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+    public sealed class DoesNotReturnIfAttribute : Attribute
+    {
+        /// <summary>Initializes the attribute with the specified parameter value.</summary>
+        /// <param name="parameterValue">
+        /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to
+        /// the associated parameter matches this value.
+        /// </param>
+        public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;
+
+        /// <summary>Gets the condition parameter value.</summary>
+        public bool ParameterValue { get; }
+    }
+}
index 13d13f1..af6c1a3 100644 (file)
@@ -18,6 +18,7 @@
 #define DEBUG // The behavior of this contract library should be consistent regardless of build type.
 
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 
 namespace System.Diagnostics.Contracts
@@ -245,7 +246,7 @@ namespace System.Diagnostics.Contracts
         [Pure]
         [Conditional("DEBUG")]
         [Conditional("CONTRACTS_FULL")]
-        public static void Assume(bool condition)
+        public static void Assume([DoesNotReturnIf(false)] bool condition)
         {
             if (!condition)
             {
@@ -264,7 +265,7 @@ namespace System.Diagnostics.Contracts
         [Pure]
         [Conditional("DEBUG")]
         [Conditional("CONTRACTS_FULL")]
-        public static void Assume(bool condition, string? userMessage)
+        public static void Assume([DoesNotReturnIf(false)] bool condition, string? userMessage)
         {
             if (!condition)
             {
@@ -283,7 +284,7 @@ namespace System.Diagnostics.Contracts
         [Pure]
         [Conditional("DEBUG")]
         [Conditional("CONTRACTS_FULL")]
-        public static void Assert(bool condition)
+        public static void Assert([DoesNotReturnIf(false)] bool condition)
         {
             if (!condition)
                 ReportFailure(ContractFailureKind.Assert, null, null, null);
@@ -297,7 +298,7 @@ namespace System.Diagnostics.Contracts
         [Pure]
         [Conditional("DEBUG")]
         [Conditional("CONTRACTS_FULL")]
-        public static void Assert(bool condition, string? userMessage)
+        public static void Assert([DoesNotReturnIf(false)] bool condition, string? userMessage)
         {
             if (!condition)
                 ReportFailure(ContractFailureKind.Assert, userMessage, null, null);
index 8d77fc2..251ac22 100644 (file)
@@ -4,6 +4,8 @@
 
 // Do not remove this, it is needed to retain calls to these conditional methods in release builds
 #define DEBUG
+
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Diagnostics
@@ -85,19 +87,19 @@ namespace System.Diagnostics
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
-        public static void Assert(bool condition)
+        public static void Assert([DoesNotReturnIf(false)] bool condition)
         {
             Assert(condition, string.Empty, string.Empty);
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
-        public static void Assert(bool condition, string? message)
+        public static void Assert([DoesNotReturnIf(false)] bool condition, string? message)
         {
             Assert(condition, message, string.Empty);
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
-        public static void Assert(bool condition, string? message, string? detailMessage)
+        public static void Assert([DoesNotReturnIf(false)] bool condition, string? message, string? detailMessage)
         {
             if (!condition)
             {
@@ -121,19 +123,21 @@ namespace System.Diagnostics
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
+        [DoesNotReturn]
         public static void Fail(string? message)
         {
             Fail(message, string.Empty);
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
+        [DoesNotReturn]
         public static void Fail(string? message, string? detailMessage)
         {
             s_provider.Fail(message, detailMessage);
         }
 
         [System.Diagnostics.Conditional("DEBUG")]
-        public static void Assert(bool condition, string? message, string detailMessageFormat, params object?[] args)
+        public static void Assert([DoesNotReturnIf(false)] bool condition, string? message, string detailMessageFormat, params object?[] args)
         {
             Assert(condition, message, string.Format(detailMessageFormat, args));
         }
index 2e82810..939f371 100644 (file)
@@ -97,7 +97,7 @@ namespace System.Diagnostics
             int indentCount = Debug.IndentSize * Debug.IndentLevel;
             if (_indentString?.Length == indentCount)
             {
-                return _indentString!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34942
+                return _indentString!; // TODO-NULLABLE: Null conditional access (https://github.com/dotnet/roslyn/issues/34942)
             }
             return _indentString = new string(' ', indentCount);
         }
index 1e3e9f6..107d4eb 100644 (file)
@@ -226,7 +226,7 @@ namespace System.Diagnostics
                         isAsync = typeof(IAsyncStateMachine).IsAssignableFrom(declaringType);
                         if (isAsync || typeof(IEnumerator).IsAssignableFrom(declaringType))
                         {
-                            methodChanged = TryResolveStateMachineMethod(ref mb!, out declaringType); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            methodChanged = TryResolveStateMachineMethod(ref mb!, out declaringType); // TODO-NULLABLE: Pass non-null string? to string ref (https://github.com/dotnet/roslyn/issues/34874)
                         }
                     }
 
index 84450ab..af48288 100644 (file)
@@ -59,7 +59,7 @@ namespace System.Diagnostics.Tracing
             if (_group != null)
             {
                 _group.Remove(this);
-                _group = null!; // TODO-NULLABLE: should not be nulled out
+                _group = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
             }
         }
 
index caa7fae..fde1b47 100644 (file)
@@ -322,7 +322,7 @@ namespace System.Diagnostics.Tracing
                             GetDataFromController(etwSessionId, filterData, out command, out data, out keyIndex))
                         {
                             args = new Dictionary<string, string>(4);
-                            Debug.Assert(data != null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            Debug.Assert(data != null);
                             while (keyIndex < data.Length)
                             {
                                 int keyEnd = FindNull(data, keyIndex);
@@ -602,7 +602,7 @@ namespace System.Diagnostics.Tracing
         /// starts, and the command being issued associated with that data.  
         /// </summary>
         private unsafe bool GetDataFromController(int etwSessionId,
-                Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[]? data, out int dataStart)
+            Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[]? data, out int dataStart)
         {
             data = null;
             dataStart = 0;
index 9f59da9..6412676 100644 (file)
 // opportunity to expose this format to EventListeners in the future.   
 // 
 using System;
-using System.Runtime.CompilerServices;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
@@ -1365,14 +1364,14 @@ namespace System.Diagnostics.Tracing
                 if (m_etwProvider != null)
                 {
                     m_etwProvider.Dispose();
-                    m_etwProvider = null!; // TODO-NULLABLE: should not be nulled out on Dispose
+                    m_etwProvider = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
                 }
 #endif
 #if FEATURE_PERFTRACING
                 if (m_eventPipeProvider != null)
                 {
                     m_eventPipeProvider.Dispose();
-                    m_eventPipeProvider = null!; // TODO-NULLABLE: should not be nulled out on Dispose
+                    m_eventPipeProvider = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
                 }
 #endif
             }
@@ -1735,7 +1734,7 @@ namespace System.Diagnostics.Tracing
             hash.Start();
             hash.Append(namespaceBytes);
             hash.Append(bytes);
-            Array.Resize(ref bytes!, 16); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Array.Resize(ref bytes!, 16); // TODO-NULLABLE: Remove ! when nullable attributes are respected
             hash.Finish(bytes);
 
             bytes[7] = unchecked((byte)((bytes[7] & 0x0F) | 0x50));    // Set high 4 bits of octet 7 to 5, as per RFC 4122
@@ -3106,7 +3105,7 @@ namespace System.Diagnostics.Tracing
 
                         foreach (CustomAttributeNamedArgument namedArgument in data.NamedArguments)
                         {
-                            PropertyInfo p = t.GetProperty(namedArgument.MemberInfo.Name, BindingFlags.Public | BindingFlags.Instance)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            PropertyInfo p = t.GetProperty(namedArgument.MemberInfo.Name, BindingFlags.Public | BindingFlags.Instance)!;
                             object value = namedArgument.TypedValue.Value!;
 
                             if (p.PropertyType.IsEnum)
@@ -3430,7 +3429,7 @@ namespace System.Diagnostics.Tracing
                             // overwrite inline message with the localized message
                             if (msg != null) eventAttribute.Message = msg;
 
-                            AddEventDescriptor(ref eventData!, eventName, eventAttribute, args, hasRelatedActivityID); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34874
+                            AddEventDescriptor(ref eventData!, eventName, eventAttribute, args, hasRelatedActivityID); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         }
                     }
                 }
@@ -3441,7 +3440,7 @@ namespace System.Diagnostics.Tracing
                 if (source != null)
                 {
                     Debug.Assert(eventData != null);
-                    TrimEventDescriptors(ref eventData!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34874
+                    TrimEventDescriptors(ref eventData!); // TODO-NULLABLE: Pass non-null string? to string ref (https://github.com/dotnet/roslyn/issues/34874)
                     source.m_eventData = eventData;     // officially initialize it. We do this at most once (it is racy otherwise). 
 #if FEATURE_MANAGED_ETW_CHANNELS
                     source.m_channelData = manifest.GetChannelData();
@@ -3473,12 +3472,11 @@ namespace System.Diagnostics.Tracing
                 exception = e;
             }
 
-            // TODO-NULLABLE: possible bug: if error is thrown before manifest is assigned in non-strict mode, this will NRE
-            if ((flags & EventManifestOptions.Strict) != 0 && (manifest!.Errors.Count > 0 || exception != null))
+            if ((flags & EventManifestOptions.Strict) != 0 && (manifest?.Errors.Count > 0 || exception != null))
             {
                 string msg = string.Empty;
 
-                if (manifest.Errors.Count > 0)
+                if (manifest?.Errors.Count > 0)
                 {
                     bool firstError = true;
                     foreach (string error in manifest.Errors)
@@ -3554,13 +3552,15 @@ namespace System.Diagnostics.Tracing
         // Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method
         // with the code:EventAttribute 'eventAttribute'.  resourceManger may be null in which case we populate it
         // it is populated if we need to look up message resources
-        private static void AddEventDescriptor(ref EventMetadata[] eventData, string eventName,
-                                EventAttribute eventAttribute, ParameterInfo[] eventParameters,
-                                bool hasRelatedActivityID)
+        private static void AddEventDescriptor(
+            [NotNull] ref EventMetadata[] eventData,
+            string eventName,
+            EventAttribute eventAttribute,
+            ParameterInfo[] eventParameters,
+            bool hasRelatedActivityID)
         {
-            if (eventData == null || eventData.Length <= eventAttribute.EventId)
+            if (eventData.Length <= eventAttribute.EventId)
             {
-                Debug.Assert(eventData != null); // TODO-NULLABLE: possible bug in the code: NRE when eventData == null
                 EventMetadata[] newValues = new EventMetadata[Math.Max(eventData.Length + 16, eventAttribute.EventId + 1)];
                 Array.Copy(eventData, 0, newValues, 0, eventData.Length);
                 eventData = newValues;
@@ -4509,7 +4509,7 @@ namespace System.Diagnostics.Tracing
             {
                 if (s_EventSources == null)
                     Interlocked.CompareExchange(ref s_EventSources, new List<WeakReference>(2), null);
-                return s_EventSources!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34901
+                return s_EventSources!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -6045,7 +6045,7 @@ namespace System.Diagnostics.Tracing
             if (resources != null && eventMessage == null)
                 eventMessage = resources.GetString("event_" + eventName, CultureInfo.InvariantCulture);
 
-            Debug.Assert(info.Attribs != null); // TODO-NULLABLE: Bug - Attribs is documented that it can be null in which case this code will NRE
+            Debug.Assert(info.Attribs != null);
             if (info.Attribs.EventChannelType == EventChannelType.Admin && eventMessage == null)
                 ManifestError(SR.Format(SR.EventSource_EventWithAdminChannelMustHaveMessage, eventName, info.Name));
             return info.Name;
@@ -6187,7 +6187,7 @@ namespace System.Diagnostics.Tracing
             }
         }
 
-        private static void UpdateStringBuilder(ref StringBuilder? stringBuilder, string eventMessage, int startIndex, int count) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 nullable in, non-nullable out
+        private static void UpdateStringBuilder([NotNull] ref StringBuilder? stringBuilder, string eventMessage, int startIndex, int count)
         {
             if (stringBuilder == null)
                 stringBuilder = new StringBuilder();
@@ -6209,14 +6209,14 @@ namespace System.Diagnostics.Tracing
                     if (stringBuilder == null)
                         return eventMessage;
                     UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
-                    return stringBuilder!.ToString(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    return stringBuilder!.ToString(); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
 
                 if (eventMessage[i] == '%')
                 {
                     // handle format message escaping character '%' by escaping it
                     UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
-                    stringBuilder!.Append("%%"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    stringBuilder!.Append("%%"); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     i++;
                     writtenSoFar = i;
                 }
@@ -6225,7 +6225,7 @@ namespace System.Diagnostics.Tracing
                 {
                     // handle C# escaped '{" and '}'
                     UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
-                    stringBuilder!.Append(eventMessage[i]); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    stringBuilder!.Append(eventMessage[i]); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     i++; i++;
                     writtenSoFar = i;
                 }
@@ -6244,7 +6244,7 @@ namespace System.Diagnostics.Tracing
                         i++;
                         UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, leftBracket - writtenSoFar);
                         int manIndex = TranslateIndexToManifestConvention(argNum, evtName);
-                        stringBuilder!.Append('%').Append(manIndex); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        stringBuilder!.Append('%').Append(manIndex); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         // An '!' after the insert specifier {n} will be interpreted as a literal.
                         // We'll escape it so that mc.exe does not attempt to consider it the 
                         // beginning of a format string.
@@ -6264,7 +6264,7 @@ namespace System.Diagnostics.Tracing
                 {
                     UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
                     i++;
-                    stringBuilder!.Append(s_escapes[chIdx]); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    stringBuilder!.Append(s_escapes[chIdx]); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     writtenSoFar = i;
                 }
                 else
index a15dfaa..fca673d 100644 (file)
@@ -110,7 +110,7 @@ namespace System.Diagnostics.Tracing
                 Array.Copy(oldItems, lo, newItems, lo + 1, oldLength - lo);
             }
 
-            newItems = Interlocked.CompareExchange(ref this.items, newItems, oldItems)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34901
+            newItems = Interlocked.CompareExchange(ref this.items, newItems, oldItems)!;
             if (oldItems != newItems)
             {
                 oldItems = newItems;
index 010d512..3572352 100644 (file)
@@ -3,9 +3,10 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
-using System.Collections.Generic;
 using System.Collections;
+using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 #if !ES_BUILD_AGAINST_DOTNET_V35
 using Contract = System.Diagnostics.Contracts.Contract;
@@ -128,7 +129,7 @@ namespace System.Diagnostics.Tracing
             throw new System.NotSupportedException();
         }
        
-        public bool TryGetValue(string key, out object? value)
+        public bool TryGetValue(string key, [MaybeNullWhen(false)] out object? value)
         {
             if (key == null)
                 throw new System.ArgumentNullException(nameof(key));
index 61ed204..3d0afdd 100644 (file)
@@ -241,32 +241,32 @@ namespace System.Diagnostics.Tracing
                 if (!Statics.IsValueType(type))
                 {
                     var getter = (Func<TContainer, object?>)GetGetMethod(property, type);
-                    return container => new PropertyValue(getter((TContainer)container.ReferenceValue!)); // TODO-NULLABLE-GENERIC: Re-review
+                    return container => new PropertyValue(getter((TContainer)container.ReferenceValue!));
                 }
                 else
                 {
                     if (type.GetTypeInfo().IsEnum)
                         type = Enum.GetUnderlyingType(type);
 
-                    if (type == typeof(bool)) { var f = (Func<TContainer, bool>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(byte)) { var f = (Func<TContainer, byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(sbyte)) { var f = (Func<TContainer, sbyte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(char)) { var f = (Func<TContainer, char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(short)) { var f = (Func<TContainer, short>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(ushort)) { var f = (Func<TContainer, ushort>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(int)) { var f = (Func<TContainer, int>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(uint)) { var f = (Func<TContainer, uint>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(long)) { var f = (Func<TContainer, long>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(ulong)) { var f = (Func<TContainer, ulong>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(float)) { var f = (Func<TContainer, float>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(double)) { var f = (Func<TContainer, double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
-                    if (type == typeof(decimal)) { var f = (Func<TContainer, decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); } // TODO-NULLABLE-GENERIC: Re-review
+                    if (type == typeof(bool)) { var f = (Func<TContainer, bool>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(byte)) { var f = (Func<TContainer, byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(sbyte)) { var f = (Func<TContainer, sbyte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(char)) { var f = (Func<TContainer, char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(short)) { var f = (Func<TContainer, short>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(ushort)) { var f = (Func<TContainer, ushort>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(int)) { var f = (Func<TContainer, int>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(uint)) { var f = (Func<TContainer, uint>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(long)) { var f = (Func<TContainer, long>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(ulong)) { var f = (Func<TContainer, ulong>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(float)) { var f = (Func<TContainer, float>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(double)) { var f = (Func<TContainer, double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
+                    if (type == typeof(decimal)) { var f = (Func<TContainer, decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue!)); }
 
                     return container => new PropertyValue(property.GetValue(container.ReferenceValue));
                 }
index 379a67a..0affe93 100644 (file)
@@ -10,6 +10,7 @@ using System.Runtime.CompilerServices;
 using Encoding = System.Text.Encoding;
 
 using Microsoft.Reflection;
+using System.Diagnostics.CodeAnalysis;
 
 #if ES_BUILD_STANDALONE
 using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
@@ -421,10 +422,10 @@ namespace System.Diagnostics.Tracing
             return result;
         }
 
-        public static AttributeType GetCustomAttribute<AttributeType>(PropertyInfo propInfo)
-            where AttributeType : Attribute?
+        public static AttributeType? GetCustomAttribute<AttributeType>(PropertyInfo propInfo)
+            where AttributeType : Attribute
         {
-            AttributeType result = null!; // TODO-NULLABLE-GENERIC: re-review
+            AttributeType? result = null;
 #if (ES_BUILD_PCL || ES_BUILD_PN)
             foreach (var attrib in propInfo.GetCustomAttributes<AttributeType>(false))
             {
@@ -441,10 +442,10 @@ namespace System.Diagnostics.Tracing
             return result;
         }
 
-        public static AttributeType GetCustomAttribute<AttributeType>(Type type)
-            where AttributeType : Attribute?
+        public static AttributeType? GetCustomAttribute<AttributeType>(Type type)
+            where AttributeType : Attribute
         {
-            AttributeType result = null!; // TODO-NULLABLE-GENERIC: re-review
+            AttributeType? result = null;
 #if (ES_BUILD_PCL || ES_BUILD_PN)
             foreach (var attrib in type.GetTypeInfo().GetCustomAttributes<AttributeType>(false))
             {
@@ -537,9 +538,9 @@ namespace System.Diagnostics.Tracing
 
             recursionCheck.Add(dataType);
 
-            var eventAttrib = Statics.GetCustomAttribute<EventDataAttribute?>(dataType);
+            var eventAttrib = Statics.GetCustomAttribute<EventDataAttribute>(dataType);
             if (eventAttrib != null ||
-                Statics.GetCustomAttribute<CompilerGeneratedAttribute?>(dataType) != null ||
+                Statics.GetCustomAttribute<CompilerGeneratedAttribute>(dataType) != null ||
                 IsGenericMatch(dataType, typeof(KeyValuePair<,>)))
             {
                 var analysis = new TypeAnalysis(dataType, eventAttrib, recursionCheck);
index 3ade2b2..ff99f5e 100644 (file)
@@ -59,7 +59,7 @@ namespace System.Diagnostics.Tracing
 
                 var propertyType = propertyInfo.PropertyType;
                 var propertyTypeInfo = TraceLoggingTypeInfo.GetInstance(propertyType, recursionCheck);
-                var fieldAttribute = Statics.GetCustomAttribute<EventFieldAttribute?>(propertyInfo);
+                var fieldAttribute = Statics.GetCustomAttribute<EventFieldAttribute>(propertyInfo);
 
                 string propertyName =
                     fieldAttribute != null && fieldAttribute.Name != null
index 0f07c75..df7c1ee 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Reflection;
 using System.Runtime.CompilerServices;
@@ -493,7 +494,7 @@ namespace System
 
                 default:
                     parsed = TryParseRareEnum(rt, value, valueSpan, ignoreCase, throwOnFailure, out object? objectResult);
-                    result = parsed ? (TEnum)objectResult! : default; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                    result = parsed ? (TEnum)objectResult! : default;
                     return parsed;
             }
         }
@@ -645,7 +646,7 @@ namespace System
         }
 
         /// <summary>Tries to parse the value of an enum with an underlying type that can't be expressed in C# (e.g. char, bool, double, etc.)</summary>
-        private static bool TryParseRareEnum(RuntimeType enumType, string? originalValueString, ReadOnlySpan<char> value, bool ignoreCase, bool throwOnFailure, out object? result)
+        private static bool TryParseRareEnum(RuntimeType enumType, string? originalValueString, ReadOnlySpan<char> value, bool ignoreCase, bool throwOnFailure, [NotNullWhen(true)] out object? result)
         {
             Debug.Assert(
                 enumType.GetEnumUnderlyingType() != typeof(sbyte) &&
index fa343ac..0d802dc 100644 (file)
@@ -75,14 +75,16 @@ namespace System
             {
                 Debug.Assert(option == SpecialFolderOption.Create);
 
+#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
                 // TODO #11151: Replace with Directory.CreateDirectory once we have access to System.IO.FileSystem here.
                 Func<string, object> createDirectory = LazyInitializer.EnsureInitialized(ref s_directoryCreateDirectory, () =>
                 {
                     Type dirType = Type.GetType("System.IO.Directory, System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true)!;
                     MethodInfo mi = dirType.GetTypeInfo().GetDeclaredMethod("CreateDirectory")!;
                     return (Func<string, object>)mi.CreateDelegate(typeof(Func<string, object>));
-                })!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                })!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 createDirectory(path);
+#pragma warning restore CS8634
 
                 return path;
             }
index ca3b48c..d536f5c 100644 (file)
@@ -80,7 +80,7 @@ namespace System
                 {
                     foreach (string name in environmentKey.GetValueNames())
                     {
-                        string? value = environmentKey.GetValue(name, "")!.ToString(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        string? value = environmentKey.GetValue(name, "")!.ToString(); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         try
                         {
                             results.Add(name, value);
index dd3fc7f..319ae9b 100644 (file)
@@ -122,7 +122,7 @@ namespace System
                 {
                     Interlocked.CompareExchange(ref s_osVersion, GetOSVersion(), null);
                 }
-                return s_osVersion!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return s_osVersion!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -149,7 +149,7 @@ namespace System
                     versionSpan = versionSpan.Slice(0, separatorIndex);
 
                 // Return zeros rather then failing if the version string fails to parse
-                return Version.TryParse(versionSpan, out Version? version) ? version! : new Version(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return Version.TryParse(versionSpan, out Version? version) ? version! : new Version(); // TODO-NULLABLE: Remove ! when nullable attributes are respected
             }
         }
 
@@ -167,7 +167,7 @@ namespace System
                 {
                     using (currentProcess)
                     {
-                        object? result = processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                        object? result = processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null);
                         if (result is long) return (long)result;
                     }
                 }
index 61924a6..c149570 100644 (file)
@@ -35,7 +35,8 @@ namespace System.Globalization
         private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
         {
             bool result = true;
-            // TODO-NULLABLE: these can return null but are later replaced with String.Empty or other non-nullable value
+            
+            // these can return null but are later replaced with String.Empty or other non-nullable value
             result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.NativeName, out this.sNativeName!);
             result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.MonthDay, out this.sMonthDay!);
 
index f8075d4..bee8ab8 100644 (file)
@@ -100,10 +100,10 @@ namespace System.Globalization
             //
 
             // Clean up the escaping of the formats
-            this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
-            this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
-            this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
-            this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates)!;
+            this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates)!;
+            this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths)!;
+            this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay)!;
 
             return ret;
         }
index 6ca9e8d..aae2c00 100644 (file)
@@ -13,10 +13,6 @@ namespace System.Globalization
     //  NOTE: Calendars depend on the locale name that creates it.  Only a few
     //        properties are available without locales using CalendarData.GetCalendar(CalendarData)
     //
-    // TODO-NULLABLE: this class requires refactoring for proper annotations
-    //                currently from user of this class all fields are non-nullable.
-    //                To avoid potential breaking changes lots of workaround have
-    //                been used to suppress errors
     internal partial class CalendarData
     {
         // Max calendars
index 5cf1992..dd4da0d 100644 (file)
@@ -170,8 +170,8 @@ namespace System.Globalization
         [OnDeserializing]
         private void OnDeserializing(StreamingContext ctx)
         {
-            // TODO-NULLABLE: this becomes null for a brief moment before deserialization
-            //                after serialization is finished it is never null
+            // this becomes null for a brief moment before deserialization
+            // after serialization is finished it is never null.
             m_name = null!;
         }
 
index 912fce6..28315b9 100644 (file)
@@ -4,7 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Text;
 using Internal.Runtime.CompilerServices;
@@ -356,6 +356,7 @@ namespace System.Globalization
         ///
         /// We don't build the stringbuilder unless we find something to change
         /// </summary>
+        [return: NotNullIfNotNull("str")]
         internal static string? ReescapeWin32String(string? str)
         {
             // If we don't have data, then don't try anything
@@ -424,13 +425,14 @@ namespace System.Globalization
             return result.ToString();
         }
 
+        [return: NotNullIfNotNull("array")]
         internal static string[]? ReescapeWin32Strings(string[]? array)
         {
             if (array != null)
             {
                 for (int i = 0; i < array.Length; i++)
                 {
-                    array[i] = ReescapeWin32String(array[i])!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    array[i] = ReescapeWin32String(array[i])!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
             }
 
index a5d2ef6..d29668e 100644 (file)
@@ -796,9 +796,9 @@ namespace System.Globalization
                 {
                     case "zh-CHS":
                     case "zh-CHT":
-                        return _sName!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34273
+                        return _sName;
                 }
-                return _sRealName!;
+                return _sRealName;
             }
         }
 
index 3bc6288..511a440 100644 (file)
@@ -191,7 +191,7 @@ namespace System
             //
             for (int i = 0; i < formats.Length; i++)
             {
-                if (formats[i] == null || formats[i]!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                if (formats[i] == null || formats[i]!.Length == 0) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                 {
                     result.SetBadFormatSpecifierFailure();
                     return false;
index 6622e64..6a97c04 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 
 namespace System.Globalization
@@ -114,6 +115,7 @@ namespace System.Globalization
             }
         }
 
+        [DoesNotReturn]
         private static void ThrowForZeroLength(bool unicode)
         {
             int lastError = Marshal.GetLastWin32Error();
index 8e5941f..ffea420 100644 (file)
@@ -92,10 +92,10 @@ namespace System.Globalization
             Array.Resize(ref registryEraRanges, iFoundEras);
 
             // Sort them
-            Array.Sort(registryEraRanges!, CompareEraRanges); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Array.Sort(registryEraRanges!, CompareEraRanges); // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
             // Clean up era information
-            for (int i = 0; i < registryEraRanges!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            for (int i = 0; i < registryEraRanges!.Length; i++) // TODO-NULLABLE: Remove ! when nullable attributes are respected
             {
                 // eras count backwards from length to 1 (and are 1 based indexes into string arrays)
                 registryEraRanges[i].era = registryEraRanges.Length - i;
index 7190300..cdaded6 100644 (file)
@@ -201,7 +201,7 @@ namespace System.Globalization
             // If we didn't copy any then something was wrong, just return base
             if (newIndex == 0) return baseEras;
 
-            Array.Resize(ref newEras!, newIndex); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Array.Resize(ref newEras!, newIndex); // TODO-NULLABLE: Remove ! when nullable attributes are respected
             return newEras;
         }
 
index b76eeb1..89c3fa2 100644 (file)
@@ -44,7 +44,9 @@ namespace System.Globalization
             return obj is SortVersion otherVersion && Equals(otherVersion);
         }
 
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
         public bool Equals(SortVersion? other)
+#pragma warning restore CS8614
         {
             if (other == null)
             {
index d896c7d..5ff3d84 100644 (file)
@@ -50,7 +50,9 @@ namespace System.Globalization
             return true;
         }
 
-        public object? Current => GetTextElement(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8612 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
+        public object Current => GetTextElement();
+#pragma warning restore CS8612
 
         public string GetTextElement()
         {
index 1066561..6b4ea6a 100644 (file)
@@ -1690,7 +1690,7 @@ namespace System.Globalization
             // one of the formats.
             for (int i = 0; i < formats.Length; i++)
             {
-                // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                 if (formats[i] == null || formats[i]!.Length == 0)
                 {
                     return result.SetBadFormatSpecifierFailure();
index 8c4f38e..c87f572 100644 (file)
@@ -2,6 +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.Diagnostics.CodeAnalysis;
+
 namespace System
 {
     // The IComparable interface is implemented by classes that support an
@@ -32,6 +34,6 @@ namespace System
         // if this is equal to object, or a value greater than zero
         // if this is greater than object.
         // 
-        int CompareTo(T other);
+        int CompareTo([AllowNull] T other);
     }
 }
index b2c96a9..1182d02 100644 (file)
@@ -2,11 +2,13 @@
 // 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.Diagnostics.CodeAnalysis;
+
 namespace System
 {
     public interface IEquatable<T>
     {
-        bool Equals(T other);
+        bool Equals([AllowNull] T other);
     }
 }
 
index e3fe604..59cb890 100644 (file)
@@ -290,7 +290,7 @@ namespace System.IO
             // override may already exist on a derived type.
             if (_useAsyncIO && _writePos > 0)
             {
-                return new ValueTask(Task.Factory.StartNew(s => ((FileStream)s!).Dispose(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return new ValueTask(Task.Factory.StartNew(s => ((FileStream)s!).Dispose(), this,
                     CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
             }
 
@@ -364,7 +364,7 @@ namespace System.IO
             if (CanWrite)
             {
                 return Task.Factory.StartNew(
-                    state => ((FileStream)state!).FlushOSBuffer(), // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    state => ((FileStream)state!).FlushOSBuffer(),
                     this,
                     cancellationToken,
                     TaskCreationOptions.DenyChildAttach,
@@ -568,7 +568,7 @@ namespace System.IO
                 // whereas on Windows it may happen before the write has completed.
 
                 Debug.Assert(t.Status == TaskStatus.RanToCompletion);
-                var thisRef = (FileStream)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var thisRef = (FileStream)s!;
                 Debug.Assert(thisRef._asyncState != null);
                 try
                 {
@@ -727,7 +727,7 @@ namespace System.IO
                 // whereas on Windows it may happen before the write has completed.
 
                 Debug.Assert(t.Status == TaskStatus.RanToCompletion);
-                var thisRef = (FileStream)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var thisRef = (FileStream)s!;
                 Debug.Assert(thisRef._asyncState != null);
                 try
                 {
index bfab0c1..be48833 100644 (file)
@@ -1587,7 +1587,7 @@ namespace System.IO
             if (CanWrite)
             {
                 return Task.Factory.StartNew(
-                    state => ((FileStream)state!).FlushOSBuffer(), // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    state => ((FileStream)state!).FlushOSBuffer(),
                     this,
                     cancellationToken,
                     TaskCreationOptions.DenyChildAttach,
index b8a11d9..11a41f7 100644 (file)
@@ -451,7 +451,7 @@ namespace System.IO
                 // it then fall back to doing the ArrayPool/copy behavior.
                 return new ValueTask<int>(
                     MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> destinationArray) ?
-                        Read(destinationArray.Array!, destinationArray.Offset, destinationArray.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        Read(destinationArray.Array!, destinationArray.Offset, destinationArray.Count) :
                         Read(buffer.Span));
             }
             catch (OperationCanceledException oce)
@@ -766,7 +766,7 @@ namespace System.IO
                 // Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
                 if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> sourceArray))
                 {
-                    Write(sourceArray.Array!, sourceArray.Offset, sourceArray.Count); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    Write(sourceArray.Array!, sourceArray.Offset, sourceArray.Count);
                 }
                 else
                 {
index 674cc6e..b0c3df3 100644 (file)
@@ -4,6 +4,7 @@
 
 #nullable enable
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Text;
 
@@ -46,7 +47,8 @@ namespace System.IO
         // returns null. If path does not contain a file extension,
         // the new file extension is appended to the path. If extension
         // is null, any existing extension is removed from path.
-        public static string? ChangeExtension(string? path, string? extension) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("path")]
+        public static string? ChangeExtension(string? path, string? extension)
         {
             if (path == null)
                 return null;
@@ -99,7 +101,7 @@ namespace System.IO
         /// <remarks>
         /// Directory separators are normalized in the returned string.
         /// </remarks>
-        public static string? GetDirectoryName(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static string? GetDirectoryName(string? path)
         {
             if (path == null || PathInternal.IsEffectivelyEmpty(path.AsSpan()))
                 return null;
@@ -147,7 +149,8 @@ namespace System.IO
         /// The returned value is null if the given path is null or empty if the given path does not include an
         /// extension.
         /// </summary>
-        public static string? GetExtension(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("path")]
+        public static string? GetExtension(string? path)
         {
             if (path == null)
                 return null;
@@ -186,6 +189,7 @@ namespace System.IO
         /// the characters of path that follow the last separator in path. The resulting string is
         /// null if path is null.
         /// </summary>
+        [return: NotNullIfNotNull("path")]
         public static string? GetFileName(string? path)
         {
             if (path == null)
@@ -217,7 +221,8 @@ namespace System.IO
             return path;
         }
 
-        public static string? GetFileNameWithoutExtension(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("path")]
+        public static string? GetFileNameWithoutExtension(string? path)
         {
             if (path == null)
                 return null;
index 40ed96f..8247465 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 #nullable enable
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Text;
 
@@ -87,6 +88,7 @@ namespace System.IO
         /// away from paths during normalization, but if we see such a path at this point it should be
         /// normalized and has retained the final characters. (Typically from one of the *Info classes)
         /// </summary>
+        [return: NotNullIfNotNull("path")]
         internal static string? EnsureExtendedPrefixIfNeeded(string? path)
         {
             if (path != null && (path.Length >= MaxShortPath || EndsWithPeriodOrSpace(path)))
index e6288cb..51cc816 100644 (file)
@@ -42,7 +42,11 @@ namespace System.IO
         {
             // Lazily-initialize _asyncActiveSemaphore.  As we're never accessing the SemaphoreSlim's
             // WaitHandle, we don't need to worry about Disposing it.
-            return LazyInitializer.EnsureInitialized<SemaphoreSlim>(ref _asyncActiveSemaphore!, () => new SemaphoreSlim(1, 1)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
+#pragma warning disable CS8603 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
+            return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
+#pragma warning restore CS8603
+#pragma warning restore CS8634
         }
 
         public abstract bool CanRead
@@ -255,7 +259,7 @@ namespace System.IO
 
         public virtual Task FlushAsync(CancellationToken cancellationToken)
         {
-            return Task.Factory.StartNew(state => ((Stream)state!).Flush(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            return Task.Factory.StartNew(state => ((Stream)state!).Flush(), this,
                 cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
 
@@ -380,7 +384,7 @@ namespace System.IO
         {
             if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
             {
-                return new ValueTask<int>(ReadAsync(array.Array!, array.Offset, array.Count, cancellationToken)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return new ValueTask<int>(ReadAsync(array.Array!, array.Offset, array.Count, cancellationToken));
             }
             else
             {
@@ -511,7 +515,7 @@ namespace System.IO
                 asyncWaiter.ContinueWith((t, state) =>
                 {
                     Debug.Assert(t.IsCompletedSuccessfully, "The semaphore wait should always complete successfully.");
-                    var rwt = (ReadWriteTask)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    var rwt = (ReadWriteTask)state!;
                     Debug.Assert(rwt._stream != null);
                     rwt._stream.RunReadWriteTask(rwt); // RunReadWriteTask(readWriteTask);
                 }, readWriteTask, default, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
@@ -691,7 +695,7 @@ namespace System.IO
         {
             if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
             {
-                return new ValueTask(WriteAsync(array.Array!, array.Offset, array.Count, cancellationToken)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return new ValueTask(WriteAsync(array.Array!, array.Offset, array.Count, cancellationToken));
             }
             else
             {
@@ -1061,7 +1065,7 @@ namespace System.IO
             {
                 get
                 {
-                    return LazyInitializer.EnsureInitialized<ManualResetEvent>(ref _waitHandle!, () => new ManualResetEvent(true)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    return LazyInitializer.EnsureInitialized<ManualResetEvent>(ref _waitHandle!, () => new ManualResetEvent(true)); // Remove ! when nullable attributes are respected
                 }
             }
 
index a59ac58..0ebcede 100644 (file)
@@ -84,6 +84,7 @@ namespace System.IO
             }
         }
 
+        [DoesNotReturn]
         private static void ThrowAsyncIOInProgress() =>
             throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
 
index 87557e8..9d143ed 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -56,6 +57,7 @@ namespace System.IO
             }
         }
 
+        [DoesNotReturn]
         private static void ThrowAsyncIOInProgress() =>
             throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
 
index a49463f..5afc919 100644 (file)
@@ -209,7 +209,7 @@ namespace System.IO
         {
             return Task<string?>.Factory.StartNew(state =>
             {
-                return ((TextReader)state!).ReadLine(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return ((TextReader)state!).ReadLine();
             },
             this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
@@ -253,10 +253,10 @@ namespace System.IO
 
         public virtual ValueTask<int> ReadAsync(Memory<char> buffer, CancellationToken cancellationToken = default) =>
             new ValueTask<int>(MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
-                ReadAsync(array.Array!, array.Offset, array.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                ReadAsync(array.Array!, array.Offset, array.Count) :
                 Task<int>.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextReader, Memory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    var t = (Tuple<TextReader, Memory<char>>)state!;
                     return t.Item1.Read(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
 
@@ -265,7 +265,7 @@ namespace System.IO
             var tuple = new Tuple<TextReader, Memory<char>>(this, buffer);
             return new ValueTask<int>(Task<int>.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextReader, Memory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextReader, Memory<char>>)state!;
                 return t.Item1.Read(t.Item2.Span);
             },
             tuple, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
@@ -291,10 +291,10 @@ namespace System.IO
 
         public virtual ValueTask<int> ReadBlockAsync(Memory<char> buffer, CancellationToken cancellationToken = default) =>
             new ValueTask<int>(MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
-                ReadBlockAsync(array.Array!, array.Offset, array.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                ReadBlockAsync(array.Array!, array.Offset, array.Count) :
                 Task<int>.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextReader, Memory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    var t = (Tuple<TextReader, Memory<char>>)state!;
                     return t.Item1.ReadBlock(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
 
index 890c35e..9dfb140 100644 (file)
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Buffers;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.IO
 {
@@ -117,7 +118,8 @@ namespace System.IO
         /// the TextWriter to be readable by a TextReader, only one of the following line
         /// terminator strings should be used: "\r", "\n", or "\r\n".
         /// </remarks>
-        public virtual string? NewLine // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+        [AllowNull]
+        public virtual string NewLine
         {
             get { return CoreNewLineStr; }
             set
@@ -545,7 +547,7 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, char>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, char>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextWriter, char>)state!;
                 t.Item1.Write(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -556,7 +558,7 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, string?>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, string?>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextWriter, string?>)state!;
                 t.Item1.Write(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -598,7 +600,7 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, char[], int, int>(this, buffer, index, count);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, char[], int, int>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextWriter, char[], int, int>)state!;
                 t.Item1.Write(t.Item2, t.Item3, t.Item4);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -606,11 +608,11 @@ namespace System.IO
 
         public virtual Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
             cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
-            MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ? // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
                 WriteAsync(array.Array!, array.Offset, array.Count) :
                 Task.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!;
                     t.Item1.Write(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
 
@@ -619,7 +621,7 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, char>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, char>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextWriter, char>)state!;
                 t.Item1.WriteLine(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -630,7 +632,7 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, string?>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, string?>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextWriter, string?>)state!;
                 t.Item1.WriteLine(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -673,7 +675,7 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, char[], int, int>(this, buffer, index, count);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, char[], int, int>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var t = (Tuple<TextWriter, char[], int, int>)state!;
                 t.Item1.WriteLine(t.Item2, t.Item3, t.Item4);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -681,11 +683,11 @@ namespace System.IO
 
         public virtual Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
             cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
-            MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ? // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
                 WriteLineAsync(array.Array!, array.Offset, array.Count) :
                 Task.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!;
                     t.Item1.WriteLine(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
 
@@ -698,7 +700,7 @@ namespace System.IO
         {
             return Task.Factory.StartNew(state =>
             {
-                ((TextWriter)state!).Flush(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                ((TextWriter)state!).Flush();
             },
             this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
@@ -766,7 +768,8 @@ namespace System.IO
 
             public override IFormatProvider FormatProvider => _out.FormatProvider;
 
-            public override string? NewLine
+            [AllowNull]
+            public override string NewLine
             {
                 [MethodImpl(MethodImplOptions.Synchronized)]
                 get { return _out.NewLine; }
index eeaed0a..e6f67bc 100644 (file)
@@ -511,7 +511,7 @@ namespace System.IO
                 // it then fall back to doing the ArrayPool/copy behavior.
                 return new ValueTask<int>(
                     MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> destinationArray) ?
-                        Read(destinationArray.Array!, destinationArray.Offset, destinationArray.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        Read(destinationArray.Array!, destinationArray.Offset, destinationArray.Count) :
                         Read(buffer.Span));
             }
             catch (Exception ex)
@@ -796,7 +796,7 @@ namespace System.IO
                 // Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
                 if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> sourceArray))
                 {
-                    Write(sourceArray.Array!, sourceArray.Offset, sourceArray.Count); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    Write(sourceArray.Array!, sourceArray.Offset, sourceArray.Count);
                 }
                 else
                 {
index 5bd3a9a..b341136 100644 (file)
@@ -11,6 +11,7 @@
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.ExceptionServices;
 using System.Threading;
 
@@ -87,6 +88,7 @@ namespace System
             _exceptionDispatch = ExceptionDispatchInfo.Capture(exception);
         }
 
+        [DoesNotReturn]
         internal void ThrowException()
         {
             Debug.Assert(_exceptionDispatch != null, "execution path is invalid");
@@ -192,7 +194,7 @@ namespace System
         private Func<T>? _factory;
 
         // _value eventually stores the lazily created value. It is valid when _state = null.
-        private T _value = default!; // TODO-NULLABLE-GENERIC
+        private T _value = default!;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class that 
@@ -444,13 +446,14 @@ namespace System
         }
 
         /// <summary>Gets the value of the Lazy&lt;T&gt; for debugging display purposes.</summary>
+        [MaybeNull]
         internal T ValueForDebugDisplay
         {
             get
             {
                 if (!IsValueCreated)
                 {
-                    return default!; // TODO-NULLABLE-GENERIC
+                    return default!;
                 }
                 return _value;
             }
index ac9be48..014589c 100644 (file)
@@ -14,6 +14,7 @@
 //This class contains only static members and doesn't require serialization.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime;
 using System.Runtime.CompilerServices;
 using System.Runtime.Versioning;
@@ -99,6 +100,7 @@ namespace System
             return decimal.Abs(value);
         }
 
+        [DoesNotReturn]
         [StackTraceHidden]
         private static void ThrowAbsOverflow()
         {
@@ -984,6 +986,7 @@ namespace System
             return d;
         }
 
+        [DoesNotReturn]
         private static void ThrowMinMaxException<T>(T min, T max)
         {
             throw new ArgumentException(SR.Format(SR.Argument_MinMaxValue, min, max));
index 54f0147..6d63973 100644 (file)
@@ -54,7 +54,7 @@ namespace System
                 this = default;
                 return; // returns default
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
 
             _object = array;
@@ -72,7 +72,7 @@ namespace System
                 this = default;
                 return; // returns default
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
             if ((uint)start > (uint)array.Length)
                 ThrowHelper.ThrowArgumentOutOfRangeException();
@@ -104,7 +104,7 @@ namespace System
                 this = default;
                 return; // returns default
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
 #if BIT64
             // See comment in Span<T>.Slice for how this works.
index 4af4937..6de285d 100644 (file)
@@ -237,7 +237,7 @@ namespace System
             if (GlobalizationMode.Invariant)
                 TextInfo.ToLowerAsciiInvariant(source, destination);
             else
-                culture!.TextInfo.ChangeCaseToLower(source, destination); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                culture!.TextInfo.ChangeCaseToLower(source, destination); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             return source.Length;
         }
 
@@ -288,7 +288,7 @@ namespace System
             if (GlobalizationMode.Invariant)
                 TextInfo.ToUpperAsciiInvariant(source, destination);
             else
-                culture!.TextInfo.ChangeCaseToUpper(source, destination); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                culture!.TextInfo.ChangeCaseToUpper(source, destination); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             return source.Length;
         }
 
@@ -392,7 +392,7 @@ namespace System
                     ThrowHelper.ThrowArgumentOutOfRangeException();
                 return default;
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
             if ((uint)start > (uint)array.Length)
                 ThrowHelper.ThrowArgumentOutOfRangeException();
@@ -414,7 +414,7 @@ namespace System
                 return default;
             }
 
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
 
             int actualIndex = startIndex.GetOffset(array.Length);
@@ -441,7 +441,7 @@ namespace System
                 return default;
             }
 
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
 
             (int start, int length) = range.GetOffsetAndLength(array.Length);
index e304e4d..c5369d1 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -1926,8 +1927,10 @@ namespace System
             Overflow
         }
 
+        [DoesNotReturn]
         internal static void ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type = 0) => throw GetException(status, type);
 
+        [DoesNotReturn]
         internal static void ThrowOverflowException(TypeCode type) => throw GetException(ParsingStatus.Overflow, type);
 
         private static Exception GetException(ParsingStatus status, TypeCode type)
index 92b16a4..b49d8b1 100644 (file)
@@ -6,6 +6,7 @@
 #if netcoreapp
 using Internal.Runtime.CompilerServices;
 #endif
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Numerics.Hashing;
 using System.Runtime.CompilerServices;
@@ -5351,6 +5352,7 @@ namespace System.Numerics
         #endregion Same-Size Conversion
 
         #region Throw Helpers
+        [DoesNotReturn]
         internal static void ThrowInsufficientNumberOfElementsException(int requiredElementCount)
         {
             throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, requiredElementCount, "values"));
index ac64bac..ed2b606 100644 (file)
@@ -1890,6 +1890,7 @@ namespace System.Numerics
         #endregion Same-Size Conversion
 
         #region Throw Helpers
+        [DoesNotReturn]
         internal static void ThrowInsufficientNumberOfElementsException(int requiredElementCount)
         {
             throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, requiredElementCount, "values"));
index 298ca51..d5674bc 100644 (file)
@@ -76,7 +76,7 @@ namespace System.Reflection
         public sealed override Assembly Assembly => throw new NotSupportedException(SR.NotSupported_SignatureType);
         public sealed override Module Module => throw new NotSupportedException(SR.NotSupported_SignatureType);
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
         public sealed override Type ReflectedType => throw new NotSupportedException(SR.NotSupported_SignatureType);
         public sealed override Type BaseType => throw new NotSupportedException(SR.NotSupported_SignatureType);
 #pragma warning restore CS8608
@@ -86,7 +86,7 @@ namespace System.Reflection
         public sealed override int MetadataToken => throw new NotSupportedException(SR.NotSupported_SignatureType);
         public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => throw new NotSupportedException(SR.NotSupported_SignatureType);
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
         public sealed override Type DeclaringType => throw new NotSupportedException(SR.NotSupported_SignatureType);
         public sealed override MethodBase DeclaringMethod => throw new NotSupportedException(SR.NotSupported_SignatureType);
 #pragma warning restore CS8608
@@ -143,7 +143,7 @@ namespace System.Reflection
         public sealed override bool IsSubclassOf(Type c) => throw new NotSupportedException(SR.NotSupported_SignatureType);
         protected sealed override bool IsValueTypeImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
 
-#pragma warning disable CS8608 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
         public sealed override StructLayoutAttribute StructLayoutAttribute => throw new NotSupportedException(SR.NotSupported_SignatureType);
 #pragma warning restore CS8608
 
index 16c9fd0..31a8fd6 100644 (file)
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Resources
 {
-    internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<string?>, IEqualityComparer<string?> // TODO-NULLABLE: IEqualityComparer.GetHashCode does not accept nulls but Equals does
+    internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<string?>, IEqualityComparer<string?>
     {
         internal static readonly FastResourceComparer Default = new FastResourceComparer();
 
@@ -32,10 +33,9 @@ namespace System.Resources
             return FastResourceComparer.HashFunction(s);
         }
 
-        public int GetHashCode(string? key) // TODO-NULLABLE: argument should be non-nullable but IEqualityComparer.Equals accepts null
+        public int GetHashCode([DisallowNull] string? key)
         {
-            Debug.Assert(key != null, "TODO-NULLABLE");
-            return FastResourceComparer.HashFunction(key);
+            return FastResourceComparer.HashFunction(key!);
         }
 
         // This hash function MUST be publically documented with the resource
index 6dcb475..3de4b31 100644 (file)
@@ -303,7 +303,7 @@ namespace System.Resources
 
             lock (localResourceSets)
             {
-#pragma warning disable CS8619 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/35131
+#pragma warning disable CS8619 // TODO-NULLABLE: Deconstruct KeyValuePair (https://github.com/dotnet/roslyn/issues/35131)
                 foreach ((_, ResourceSet resourceSet) in localResourceSets)
 #pragma warning restore CS8619
                 {
@@ -489,7 +489,7 @@ namespace System.Resources
                 // that had resources.
                 foreach (CultureInfo updateCultureInfo in mgr)
                 {
-                    AddResourceSet(localResourceSets, updateCultureInfo.Name, ref rs!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34874
+                    AddResourceSet(localResourceSets, updateCultureInfo.Name, ref rs!); // TODO-NULLABLE: Pass non-null string? to string ref (https://github.com/dotnet/roslyn/issues/34874)
 
                     // stop when we've added current or reached invariant (top of chain)
                     if (updateCultureInfo == foundCulture)
index 86e543b..94f7f62 100644 (file)
@@ -67,6 +67,7 @@ namespace System.Resources
 
         private void InitializeBinaryFormatter()
         {
+#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
             LazyInitializer.EnsureInitialized(ref s_binaryFormatterType, () =>
                 Type.GetType("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter, System.Runtime.Serialization.Formatters, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
                 throwOnError: true));
@@ -81,6 +82,7 @@ namespace System.Resources
                         .MakeGenericMethod(s_binaryFormatterType)!
                         .Invoke(null, new object[] { binaryFormatterDeserialize })!;
             });
+#pragma warning restore CS8634
 
             _binaryFormatter = Activator.CreateInstance(s_binaryFormatterType!)!;
         }
index 4b28092..e83f166 100644 (file)
@@ -161,11 +161,11 @@ namespace System.Resources
                     // Close the stream in a thread-safe way.  This fix means
                     // that we may call Close n times, but that's safe.
                     BinaryReader copyOfStore = _store;
-                    _store = null!; // TODO-NULLABLE: dispose should not null this out
+                    _store = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
                     if (copyOfStore != null)
                         copyOfStore.Close();
                 }
-                _store = null!; // TODO-NULLABLE: dispose should not null this out
+                _store = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
                 _namePositions = null;
                 _nameHashes = null;
                 _ums = null;
@@ -960,7 +960,7 @@ namespace System.Resources
                 }
             }
             Debug.Assert(_typeTable[typeIndex] != null, "Should have found a type!");
-            return _typeTable[typeIndex]!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+            return _typeTable[typeIndex]!; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
         }
 
         private string TypeNameFromTypeCode(ResourceTypeCode typeCode)
@@ -1030,22 +1030,12 @@ namespace System.Resources
                 }
             }
 
-            public object? Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
-            {
-                get
-                {
-                    return Entry;
-                }
-            }
+#pragma warning disable CS8612 // TODO-NULLABLE: Covariant return types (https://github.com/dotnet/roslyn/issues/23268)
+            public object Current => Entry;
+#pragma warning restore CS8612
 
             // Warning: This requires that you call the Key or Entry property FIRST before calling it!
-            internal int DataPosition
-            {
-                get
-                {
-                    return _dataPosition;
-                }
-            }
+            internal int DataPosition => _dataPosition;
 
             public DictionaryEntry Entry
             {
index 936e43c..4f5edf8 100644 (file)
@@ -29,7 +29,7 @@ namespace System.Resources
     public class ResourceSet : IDisposable, IEnumerable
     {
         protected IResourceReader Reader = null!;
-        internal Hashtable? Table; // TODO-NULLABLE: should not be nulled out in Dispose
+        internal Hashtable? Table; // TODO-NULLABLE: Avoid nulling out in Dispose
 
         private Hashtable? _caseInsensitiveTable;  // For case-insensitive lookups.
 
@@ -92,11 +92,11 @@ namespace System.Resources
             {
                 // Close the Reader in a thread-safe way.
                 IResourceReader? copyOfReader = Reader;
-                Reader = null!; // TODO-NULLABLE: should not be nulled out in the Dispose
+                Reader = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
                 if (copyOfReader != null)
                     copyOfReader.Close();
             }
-            Reader = null!; // TODO-NULLABLE: should not be nulled out in the Dispose
+            Reader = null!; // TODO-NULLABLE: Avoid nulling out in Dispose
             _caseInsensitiveTable = null;
             Table = null;
         }
index 0cb229d..0d33f3a 100644 (file)
@@ -176,12 +176,12 @@ namespace System.Resources
         // for arbitrarily long times, since the object is usually a string
         // literal that will live for the lifetime of the appdomain.  The
         // value is a ResourceLocator instance, which might cache the object.
-        private Dictionary<string, ResourceLocator>? _resCache; // TODO-NULLABLE: should not be nulled out in Dispose
+        private Dictionary<string, ResourceLocator>? _resCache; // TODO-NULLABLE: Avoid nulling out in Dispose
 
 
         // For our special load-on-demand reader, cache the cast.  The 
         // RuntimeResourceSet's implementation knows how to treat this reader specially.
-        private ResourceReader? _defaultReader; // TODO-NULLABLE: should not be nulled out in Dispose
+        private ResourceReader? _defaultReader; // TODO-NULLABLE: Avoid nulling out in Dispose
 
         // This is a lookup table for case-insensitive lookups, and may be null.
         // Consider always using a case-insensitive resource cache, as we don't
index f33f0c7..9fcb418 100644 (file)
@@ -18,6 +18,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Text;
 using Internal.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.CompilerServices
 {
@@ -131,7 +132,7 @@ namespace System.Runtime.CompilerServices
                 // and decrement its outstanding operation count.
                 try
                 {
-                    System.Threading.Tasks.Task.ThrowAsync(exception!, targetContext: _synchronizationContext); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    System.Threading.Tasks.Task.ThrowAsync(exception!, targetContext: _synchronizationContext); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 }
                 finally
                 {
@@ -143,7 +144,7 @@ namespace System.Runtime.CompilerServices
                 // Otherwise, queue the exception to be thrown on the ThreadPool.  This will
                 // result in a crash unless legacy exception behavior is enabled by a config
                 // file or a CLR host.
-                System.Threading.Tasks.Task.ThrowAsync(exception!, targetContext: null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                System.Threading.Tasks.Task.ThrowAsync(exception!, targetContext: null); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             // The exception was propagated already; we don't need or want to fault the builder, just mark it as completed.
@@ -314,7 +315,7 @@ namespace System.Runtime.CompilerServices
     {
 #if !PROJECTN
         /// <summary>A cached task for default(TResult).</summary>
-        internal readonly static Task<TResult> s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE-GENERIC
+        internal readonly static Task<TResult> s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
 #endif
 
         /// <summary>The lazily-initialized built task.</summary>
@@ -396,17 +397,17 @@ namespace System.Runtime.CompilerServices
             // The null tests here ensure that the jit can optimize away the interface
             // tests when TAwaiter is a ref type.
 
-            if ((null != (object)default(TAwaiter)!) && (awaiter is ITaskAwaiter)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if ((null != (object)default(TAwaiter)!) && (awaiter is ITaskAwaiter)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 ref TaskAwaiter ta = ref Unsafe.As<TAwaiter, TaskAwaiter>(ref awaiter); // relies on TaskAwaiter/TaskAwaiter<T> having the same layout
                 TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, continueOnCapturedContext: true);
             }
-            else if ((null != (object)default(TAwaiter)!) && (awaiter is IConfiguredTaskAwaiter)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            else if ((null != (object)default(TAwaiter)!) && (awaiter is IConfiguredTaskAwaiter)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 ref ConfiguredTaskAwaitable.ConfiguredTaskAwaiter ta = ref Unsafe.As<TAwaiter, ConfiguredTaskAwaitable.ConfiguredTaskAwaiter>(ref awaiter);
                 TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, ta.m_continueOnCapturedContext);
             }
-            else if ((null != (object)default(TAwaiter)!) && (awaiter is IStateMachineBoxAwareAwaiter)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            else if ((null != (object)default(TAwaiter)!) && (awaiter is IStateMachineBoxAwareAwaiter)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 try
                 {
@@ -568,7 +569,7 @@ namespace System.Runtime.CompilerServices
             /// <summary>A delegate to the <see cref="MoveNext()"/> method.</summary>
             private Action? _moveNextAction;
             /// <summary>The state machine itself.</summary>
-            public TStateMachine StateMachine = default!; // mutable struct; do not make this readonly. SOS DumpAsync command depends on this name. // TODO-NULLABLE-GENERIC
+            [AllowNull, MaybeNull] public TStateMachine StateMachine = default!; // mutable struct; do not make this readonly. SOS DumpAsync command depends on this name.  // TODO-NULLABLE: Remove ! when nullable attributes are respected
             /// <summary>Captured ExecutionContext with which to invoke <see cref="MoveNextAction"/>; may be null.</summary>
             public ExecutionContext? Context;
 
@@ -612,7 +613,7 @@ namespace System.Runtime.CompilerServices
                     // Clear out state now that the async method has completed.
                     // This avoids keeping arbitrary state referenced by lifted locals
                     // if this Task / state machine box is held onto.
-                    StateMachine = default!; // TODO-NULLABLE-GENERIC
+                    StateMachine = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     Context = default;
 
 #if !CORERT
@@ -703,7 +704,7 @@ namespace System.Runtime.CompilerServices
 
         /// <summary>Completes the already initialized task with the specified result.</summary>
         /// <param name="result">The result to use to complete the task.</param>
-        private void SetExistingTaskResult(TResult result)
+        private void SetExistingTaskResult([AllowNull] TResult result)
         {
             Debug.Assert(m_task != null, "Expected non-null task");
 
@@ -755,7 +756,7 @@ namespace System.Runtime.CompilerServices
             else
             {
                 // Otherwise, complete the task that's there.
-                SetExistingTaskResult(default!); // TODO-NULLABLE-GENERIC
+                SetExistingTaskResult(default!); // Remove ! when nullable attributes are respected
             }
         }
 
@@ -779,7 +780,7 @@ namespace System.Runtime.CompilerServices
             // If the exception represents cancellation, cancel the task.  Otherwise, fault the task.
             bool successfullySet = exception is OperationCanceledException oce ?
                 task.TrySetCanceled(oce.CancellationToken, oce) :
-                task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             // Unlike with TaskCompletionSource, we do not need to spin here until _taskAndStateMachine is completed,
             // since AsyncTaskMethodBuilder.SetException should not be immediately followed by any code
@@ -863,7 +864,7 @@ namespace System.Runtime.CompilerServices
             // find a cached value, since static fields (even if readonly and integral types) 
             // require special access helpers in this NGEN'd and domain-neutral.
 
-            if (null != (object)default(TResult)!) // help the JIT avoid the value type branches for ref types // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (null != (object)default(TResult)!) // help the JIT avoid the value type branches for ref types // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 // Special case simple value types:
                 // - Boolean
@@ -879,7 +880,7 @@ namespace System.Runtime.CompilerServices
                 // For Boolean, we cache all possible values.
                 if (typeof(TResult) == typeof(bool)) // only the relevant branches are kept for each value-type generic instantiation
                 {
-                    bool value = (bool)(object)result!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                    bool value = (bool)(object)result!;
                     Task<bool> task = value ? AsyncTaskCache.TrueTask : AsyncTaskCache.FalseTask;
                     return Unsafe.As<Task<TResult>>(task); // UnsafeCast avoids type check we know will succeed
                 }
@@ -889,7 +890,7 @@ namespace System.Runtime.CompilerServices
                     // Compare to constants to avoid static field access if outside of cached range.
                     // We compare to the upper bound first, as we're more likely to cache miss on the upper side than on the 
                     // lower side, due to positive values being more common than negative as return values.
-                    int value = (int)(object)result!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                    int value = (int)(object)result!;
                     if (value < AsyncTaskCache.EXCLUSIVE_INT32_MAX &&
                         value >= AsyncTaskCache.INCLUSIVE_INT32_MIN)
                     {
@@ -908,7 +909,7 @@ namespace System.Runtime.CompilerServices
                     (typeof(TResult) == typeof(short) && default(short) == (short)(object)result!) ||
                     (typeof(TResult) == typeof(ushort) && default(ushort) == (ushort)(object)result!) ||
                     (typeof(TResult) == typeof(IntPtr) && default == (IntPtr)(object)result!) ||
-                    (typeof(TResult) == typeof(UIntPtr) && default == (UIntPtr)(object)result!)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                    (typeof(TResult) == typeof(UIntPtr) && default == (UIntPtr)(object)result!))
                 {
                     return s_defaultResultTask;
                 }
@@ -958,7 +959,7 @@ namespace System.Runtime.CompilerServices
         /// <typeparam name="TResult">Specifies the result type.</typeparam>
         /// <param name="result">The result for the task.</param>
         /// <returns>The cacheable task.</returns>
-        internal static Task<TResult> CreateCacheableTask<TResult>(TResult result) =>
+        internal static Task<TResult> CreateCacheableTask<TResult>([AllowNull] TResult result) =>
             new Task<TResult>(false, result, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
     }
 
@@ -1008,7 +1009,7 @@ namespace System.Runtime.CompilerServices
 
             try
             {
-                stateMachine!.MoveNext(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                stateMachine!.MoveNext(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             finally
             {
index bbbf58d..7322bbe 100644 (file)
@@ -5,6 +5,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 using Internal.Runtime.CompilerServices;
 
@@ -51,7 +52,7 @@ namespace System.Runtime.CompilerServices
         /// The key may get garbaged collected during the TryGetValue operation. If so, TryGetValue
         /// may at its discretion, return "false" and set "value" to the default (as if the key was not present.)
         /// </remarks>
-        public bool TryGetValue(TKey key, out TValue value)
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
             if (key is null)
             {
@@ -362,7 +363,7 @@ namespace System.Runtime.CompilerServices
                 }
             }
 
-            object? IEnumerator.Current => Current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+            object? IEnumerator.Current => Current;
 
             public void Reset() { }
         }
@@ -502,7 +503,7 @@ namespace System.Runtime.CompilerServices
             }
 
             /// <summary>Worker for finding a key/value pair. Must hold _lock.</summary>
-            internal bool TryGetValueWorker(TKey key, out TValue value)
+            internal bool TryGetValueWorker(TKey key, [MaybeNullWhen(false)] out TValue value)
             {
                 Debug.Assert(key != null); // Key already validated as non-null
 
@@ -536,7 +537,7 @@ namespace System.Runtime.CompilerServices
             }
 
             /// <summary>Gets the entry at the specified entry index.</summary>
-            internal bool TryGetEntry(int index, out TKey key, out TValue value)
+            internal bool TryGetEntry(int index, [MaybeNullWhen(false)] out TKey key, [MaybeNullWhen(false)] out TValue value)
             {
                 if (index < _entries.Length)
                 {
@@ -551,8 +552,8 @@ namespace System.Runtime.CompilerServices
                     }
                 }
 
-                key = default!; // TODO-NULLABLE-GENERIC
-                value = default!; // TODO-NULLABLE-GENERIC
+                key = default!;
+                value = default!;
                 return false;
             }
 
index 1b5bc37..ee9250b 100644 (file)
@@ -14,6 +14,8 @@ namespace System.Runtime.CompilerServices
             _date = new DateTime(ticks);
         }
 
-        public override object? Value => _date; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8608
+        public override object Value => _date;
+#pragma warning restore CS8608
     }
 }
index 95c5149..7320c2d 100644 (file)
@@ -2,6 +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.Diagnostics.CodeAnalysis;
+
 namespace System.Runtime.CompilerServices
 {
     /// <summary>
@@ -31,7 +33,7 @@ namespace System.Runtime.CompilerServices
         // because this is the only guard placed before an interface invocation at runtime. If a type decides
         // it no longer wants to implement a given interface it has no way to synchronize with callers that
         // have already cached this relationship and can invoke directly via the interface pointer.
-        bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception? castError);
+        bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, [NotNullWhen(true)] out Exception? castError);
 
         // This is called as part of the interface dispatch mechanism when the dispatcher logic cannot find
         // the given interface type in the interface map of this object.
index ab7b1d5..b251c0b 100644 (file)
@@ -23,9 +23,9 @@ namespace System.Runtime.CompilerServices
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
             }
 
-            (int offset, int length) = range.GetOffsetAndLength(array!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            (int offset, int length) = range.GetOffsetAndLength(array!.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
-            if (default(T)! != null || typeof(T[]) == array.GetType()) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || typeof(T[]) == array.GetType()) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 // We know the type of the array to be exactly T[].
 
index c2f681e..7b59222 100644 (file)
@@ -2,6 +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.Diagnostics.CodeAnalysis;
+
 namespace System.Runtime.CompilerServices
 {
     /// <summary>
@@ -15,7 +17,7 @@ namespace System.Runtime.CompilerServices
         /// <remarks>This is explicitly exposed as a field instead of a property to enable loading the address of the field.</remarks>
         /// </summary>
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
-        public T Value = default!; // TODO-NULLABLE-GENERIC
+        [MaybeNull] public T Value = default!;
 
         /// <summary>
         /// Initializes a new StrongBox which can receive a value when used in a reference call.
@@ -41,7 +43,7 @@ namespace System.Runtime.CompilerServices
             }
             set
             {
-                Value = (T)value!; // TODO-NULLABLE-GENERIC
+                Value = (T)value!;
             }
         }
     }
index c6b19d6..87c610f 100644 (file)
@@ -130,7 +130,7 @@ namespace System.Runtime.CompilerServices
                 SynchronizationContext? syncCtx = SynchronizationContext.Current;
                 if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
                 {
-                    syncCtx.Post(s => ((IAsyncStateMachineBox)s!).MoveNext(), box); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    syncCtx.Post(s => ((IAsyncStateMachineBox)s!).MoveNext(), box);
                 }
                 else
                 {
@@ -141,7 +141,7 @@ namespace System.Runtime.CompilerServices
                     }
                     else
                     {
-                        Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s!).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s!).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler);
                     }
                 }
             }
index 3578d43..8610978 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.ExceptionServices
 {
@@ -53,6 +54,7 @@ namespace System.Runtime.ExceptionServices
         // This method will restore the original stack trace and bucketing details before throwing
         // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on
         // the original thread.
+        [DoesNotReturn]
         [StackTraceHidden]
         public void Throw()
         {
@@ -63,6 +65,7 @@ namespace System.Runtime.ExceptionServices
 
         // Throws the source exception, maintaining the original bucketing details and augmenting
         // rather than replacing the original stack trace.
+        [DoesNotReturn]
         public static void Throw(Exception source) => Capture(source).Throw();
     }
 }
index 896312f..4ec8f58 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.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Runtime.InteropServices.ComTypes;
 
@@ -35,9 +36,8 @@ namespace System.Runtime.InteropServices
         {
         }
 
-        public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o)
+        public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o) where T : object
         {
-            // TODO-NULLABLE-GENERIC: T cannot be null
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
@@ -46,9 +46,8 @@ namespace System.Runtime.InteropServices
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
-        public static TWrapper CreateWrapperOfType<T, TWrapper>(T o)
+        public static TWrapper CreateWrapperOfType<T, TWrapper>([AllowNull] T o)
         {
-            // TODO-NULLABLE-GENERIC: T can be null
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
@@ -72,9 +71,8 @@ namespace System.Runtime.InteropServices
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
-        public static IntPtr GetComInterfaceForObject<T, TInterface>(T o)
+        public static IntPtr GetComInterfaceForObject<T, TInterface>([DisallowNull] T o)
         {
-            // TODO-NULLABLE-GENERIC: T cannot be null
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
@@ -103,9 +101,8 @@ namespace System.Runtime.InteropServices
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
-        public static void GetNativeVariantForObject<T>(T obj, IntPtr pDstNativeVariant)
+        public static void GetNativeVariantForObject<T>([AllowNull] T obj, IntPtr pDstNativeVariant)
         {
-            // TODO-NULLABLE-GENERIC: T can be null
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
@@ -124,9 +121,9 @@ namespace System.Runtime.InteropServices
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
+        [return: MaybeNull]
         public static T GetObjectForNativeVariant<T>(IntPtr pSrcNativeVariant)
         {
-            // TODO-NULLABLE-GENERIC: T can be null
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
@@ -135,7 +132,6 @@ namespace System.Runtime.InteropServices
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
-        // TODO-NULLABLE-GENERIC: T[] contents can be null
         public static T[] GetObjectsForNativeVariants<T>(IntPtr aSrcNativeVariant, int cVars)
         {
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
index f4634fd..c0e9bd6 100644 (file)
@@ -9,8 +9,6 @@ namespace System.Runtime.InteropServices
 {
     public static partial class Marshal
     {
-        // TODO-NULLABLE: This has different behavior from the other PtrToString(IntPtr, int) functions
-        //                This is due to PtrToStringUTF8 on Unix and is being resolved independently
         public static string? PtrToStringAuto(IntPtr ptr, int len)
         {
             return PtrToStringUTF8(ptr, len);
index a7ee8b3..f4027d0 100644 (file)
@@ -8,8 +8,6 @@ namespace System.Runtime.InteropServices
 {
     public static partial class Marshal
     {
-        // TODO-NULLABLE: This has different behavior from the other PtrToString(IntPtr, int) functions
-        //                This is due to PtrToStringUTF8 on Unix and is being resolved independently
         public static string? PtrToStringAuto(IntPtr ptr, int len)
         {
             return PtrToStringUni(ptr, len);
index 6834685..e9485bf 100644 (file)
@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
 using System.Text;
 
 using Internal.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 #if BIT64
 using nuint = System.UInt64;
@@ -95,8 +96,7 @@ namespace System.Runtime.InteropServices
             return string.CreateStringFromEncoding((byte*)ptr, nbBytes, Encoding.UTF8);
         }
 
-        // TODO-NULLABLE: This has different behavior from the other PtrToString(IntPtr, int) functions
-        public static unsafe string? PtrToStringUTF8(IntPtr ptr, int byteLen)
+        public static unsafe string PtrToStringUTF8(IntPtr ptr, int byteLen)
         {
             if (ptr == IntPtr.Zero)
             {
@@ -530,9 +530,8 @@ namespace System.Runtime.InteropServices
             }
         }
 
-        public static void StructureToPtr<T>(T structure, IntPtr ptr, bool fDeleteOld)
+        public static void StructureToPtr<T>([DisallowNull] T structure, IntPtr ptr, bool fDeleteOld)
         {
-            // TODO-NULLABLE-GENERIC: T cannot be null
             StructureToPtr((object)structure!, ptr, fDeleteOld);
         }
 
@@ -571,13 +570,12 @@ namespace System.Runtime.InteropServices
             PtrToStructureHelper(ptr, structure, allowValueClasses: false);
         }
 
-        public static void PtrToStructure<T>(IntPtr ptr, T structure)
+        public static void PtrToStructure<T>(IntPtr ptr, [DisallowNull] T structure)
         {
-            // TODO-NULLABLE-GENERIC: T cannot be null
             PtrToStructure(ptr, (object)structure!);
         }
 
-        // TODO-NULLABLE-GENERIC: T can be null
+        [return: MaybeNull]
         public static T PtrToStructure<T>(IntPtr ptr) => (T)PtrToStructure(ptr, typeof(T))!;
 
         public static void DestroyStructure<T>(IntPtr ptr) => DestroyStructure(ptr, typeof(T));
@@ -898,10 +896,9 @@ namespace System.Runtime.InteropServices
             return GetFunctionPointerForDelegateInternal(d);
         }
 
-        public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d)
+        public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d) where TDelegate : object
         {
-            // TODO-NULLABLE-GENERIC: T cannot be null
-            return GetFunctionPointerForDelegate((Delegate)(object)d!);
+            return GetFunctionPointerForDelegate((Delegate)(object)d);
         }
 
         public static int GetHRForLastWin32Error()
index 6816d3c..314bc02 100644 (file)
@@ -8,6 +8,7 @@ using System.Collections.Generic;
 using System.Diagnostics;
 
 using Internal.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.InteropServices
 {
@@ -55,7 +56,7 @@ namespace System.Runtime.InteropServices
                     Debug.Assert(obj is MemoryManager<T>);
                     if (Unsafe.As<MemoryManager<T>>(obj).TryGetArray(out ArraySegment<T> tempArraySegment))
                     {
-                        segment = new ArraySegment<T>(tempArraySegment.Array!, tempArraySegment.Offset + index, length); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        segment = new ArraySegment<T>(tempArraySegment.Array!, tempArraySegment.Offset + index, length);
                         return true;
                     }
                 }
@@ -86,7 +87,7 @@ namespace System.Runtime.InteropServices
         /// <param name="memory">The memory to get the manager for.</param>
         /// <param name="manager">The returned manager of the <see cref="ReadOnlyMemory{T}"/>.</param>
         /// <returns>A <see cref="bool"/> indicating if it was successful.</returns>
-        public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager? manager) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, [NotNullWhen(true)] out TManager? manager)
             where TManager : MemoryManager<T>
         {
             TManager? localManager; // Use register for null comparison rather than byref
@@ -105,7 +106,7 @@ namespace System.Runtime.InteropServices
         /// <param name="start">The offset from the start of the <paramref name="manager" /> that the <paramref name="memory" /> represents.</param>
         /// <param name="length">The length of the <paramref name="manager" /> that the <paramref name="memory" /> represents.</param>
         /// <returns>A <see cref="bool"/> indicating if it was successful.</returns>
-        public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager? manager, out int start, out int length) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, [NotNullWhen(true)] out TManager? manager, out int start, out int length)
            where TManager : MemoryManager<T>
         {
             TManager? localManager; // Use register for null comparison rather than byref
@@ -141,7 +142,7 @@ namespace System.Runtime.InteropServices
         /// <param name="start">The starting location in <paramref name="text"/>.</param>
         /// <param name="length">The number of items in <paramref name="text"/>.</param>
         /// <returns></returns>
-        public static bool TryGetString(ReadOnlyMemory<char> memory, out string? text, out int start, out int length)
+        public static bool TryGetString(ReadOnlyMemory<char> memory, [NotNullWhen(true)] out string? text, out int start, out int length)
         {
             if (memory.GetObjectStartLength(out int offset, out int count) is string s)
             {
@@ -306,7 +307,7 @@ namespace System.Runtime.InteropServices
                     ThrowHelper.ThrowArgumentOutOfRangeException();
                 return default;
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
             if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
                 ThrowHelper.ThrowArgumentOutOfRangeException();
index b50a2e6..30d50fe 100644 (file)
@@ -208,7 +208,7 @@ namespace System.Runtime.InteropServices
 
             try
             {
-                s_nativeDllResolveMap!.Add(assembly, resolver); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                s_nativeDllResolveMap!.Add(assembly, resolver); // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
             catch (ArgumentException)
             {
index 7ee3dfa..cd11839 100644 (file)
@@ -118,7 +118,7 @@ namespace System.Runtime.Loader
         private void RaiseUnloadEvent()
         {
             // Ensure that we raise the Unload event only once
-            Interlocked.Exchange(ref _unloading, null!)?.Invoke(this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Interlocked.Exchange(ref _unloading, null!)?.Invoke(this);
         }
 
         private void InitiateUnload()
@@ -442,7 +442,7 @@ namespace System.Runtime.Loader
             }
         }
 
-        private static AsyncLocal<AssemblyLoadContext>? s_asyncLocalCurrent;
+        private static AsyncLocal<AssemblyLoadContext?>? s_asyncLocalCurrent;
 
         /// <summary>Nullable current AssemblyLoadContext used for context sensitive reflection APIs</summary>
         /// <remarks>
@@ -477,9 +477,9 @@ namespace System.Runtime.Loader
         {
             if (s_asyncLocalCurrent == null)
             {
-                Interlocked.CompareExchange<AsyncLocal<AssemblyLoadContext>?>(ref s_asyncLocalCurrent, new AsyncLocal<AssemblyLoadContext>(), null);
+                Interlocked.CompareExchange<AsyncLocal<AssemblyLoadContext?>?>(ref s_asyncLocalCurrent, new AsyncLocal<AssemblyLoadContext?>(), null);
             }
-            s_asyncLocalCurrent!.Value = value!; // TODO-NULLABLE-GENERIC
+            s_asyncLocalCurrent!.Value = value; // Remove ! when compiler specially-recognizes CompareExchange for nullability
         }
 
         /// <summary>Enter scope using this AssemblyLoadContext for ContextualReflection</summary>
index 015fb00..afcf0ed 100644 (file)
@@ -539,104 +539,104 @@ namespace System.Runtime.Serialization
         public bool GetBoolean(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
-            return ReferenceEquals(foundType, typeof(bool)) ? (bool)value : _converter.ToBoolean(value); // if value is null To* method will either deal with it or throw
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(bool)) ? (bool)value! : _converter.ToBoolean(value!); // if value is null To* method will either deal with it or throw
         }
 
         public char GetChar(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(char)) ? (char)value : _converter.ToChar(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(char)) ? (char)value! : _converter.ToChar(value!);
         }
 
         [CLSCompliant(false)]
         public sbyte GetSByte(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(sbyte)) ? (sbyte)value : _converter.ToSByte(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(sbyte)) ? (sbyte)value! : _converter.ToSByte(value!);
         }
 
         public byte GetByte(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(byte)) ? (byte)value : _converter.ToByte(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(byte)) ? (byte)value! : _converter.ToByte(value!);
         }
 
         public short GetInt16(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(short)) ? (short)value : _converter.ToInt16(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(short)) ? (short)value! : _converter.ToInt16(value!);
         }
 
         [CLSCompliant(false)]
         public ushort GetUInt16(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(ushort)) ? (ushort)value : _converter.ToUInt16(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(ushort)) ? (ushort)value! : _converter.ToUInt16(value!);
         }
 
         public int GetInt32(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(int)) ? (int)value : _converter.ToInt32(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(int)) ? (int)value! : _converter.ToInt32(value!);
         }
 
         [CLSCompliant(false)]
         public uint GetUInt32(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(uint)) ? (uint)value : _converter.ToUInt32(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(uint)) ? (uint)value! : _converter.ToUInt32(value!);
         }
 
         public long GetInt64(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(long)) ? (long)value : _converter.ToInt64(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(long)) ? (long)value! : _converter.ToInt64(value!);
         }
 
         [CLSCompliant(false)]
         public ulong GetUInt64(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(ulong)) ? (ulong)value : _converter.ToUInt64(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(ulong)) ? (ulong)value! : _converter.ToUInt64(value!);
         }
 
         public float GetSingle(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(float)) ? (float)value : _converter.ToSingle(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(float)) ? (float)value! : _converter.ToSingle(value!);
         }
 
 
         public double GetDouble(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(double)) ? (double)value : _converter.ToDouble(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(double)) ? (double)value! : _converter.ToDouble(value!);
         }
 
         public decimal GetDecimal(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(decimal)) ? (decimal)value : _converter.ToDecimal(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(decimal)) ? (decimal)value! : _converter.ToDecimal(value!);
         }
 
         public DateTime GetDateTime(string name)
         {
             Type foundType;
-            object value = GetElement(name, out foundType)!;
-            return ReferenceEquals(foundType, typeof(DateTime)) ? (DateTime)value : _converter.ToDateTime(value);
+            object? value = GetElement(name, out foundType);
+            return ReferenceEquals(foundType, typeof(DateTime)) ? (DateTime)value! : _converter.ToDateTime(value!);
         }
 
         public string? GetString(string name)
index 6712a3b..65c34cb 100644 (file)
@@ -70,7 +70,7 @@ namespace System.Runtime.Serialization
             return _current;
         }
 
-        object? IEnumerator.Current => Current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        object? IEnumerator.Current => Current;
 
         public SerializationEntry Current
         {
index 456e1ec..75faa07 100644 (file)
@@ -49,7 +49,7 @@ namespace System
                 this = default;
                 return; // returns default
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
 
             _pointer = new ByReference<T>(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()));
@@ -78,7 +78,7 @@ namespace System
                 this = default;
                 return; // returns default
             }
-            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArrayTypeMismatchException();
 #if BIT64
             // See comment in Span<T>.Slice for how this works.
index 37bc43f..035e31b 100644 (file)
@@ -57,7 +57,7 @@ namespace System
 
             IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
 
-            if (default(T)! != null || (object)value != null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || (object)value != null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while (length >= 8)
                 {
@@ -127,7 +127,7 @@ namespace System
             Debug.Assert(length >= 0);
 
             IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
-            if (default(T)! != null || (object)value != null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || (object)value != null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while (length >= 8)
                 {
@@ -216,7 +216,7 @@ namespace System
 
             T lookUp;
             int index = 0;
-            if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while ((length - index) >= 8)
                 {
@@ -321,7 +321,7 @@ namespace System
 
             T lookUp;
             int index = 0;
-            if (default(T)! != null || ((object)value0 != null && (object)value1 != null && (object)value2 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || ((object)value0 != null && (object)value1 != null && (object)value2 != null)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while ((length - index) >= 8)
                 {
@@ -484,7 +484,7 @@ namespace System
         {
             Debug.Assert(length >= 0);
 
-            if (default(T)! != null || (object)value != null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || (object)value != null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while (length >= 8)
                 {
@@ -567,7 +567,7 @@ namespace System
             Debug.Assert(length >= 0);
 
             T lookUp;
-            if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while (length >= 8)
                 {
@@ -671,7 +671,7 @@ namespace System
             Debug.Assert(length >= 0);
 
             T lookUp;
-            if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
             {
                 while (length >= 8)
                 {
index a420fc8..6bf3de7 100644 (file)
@@ -522,7 +522,9 @@ namespace System
 
         // Determines the sorting relation of StrB to the current instance.
         //
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
         public int CompareTo(string? strB)
+#pragma warning restore CS8614
         {
             return string.Compare(this, strB, StringComparison.CurrentCulture);
         }
@@ -616,7 +618,9 @@ namespace System
         }
 
         // Determines whether two strings match.
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
         public bool Equals(string? value)
+#pragma warning restore CS8614
         {
             if (object.ReferenceEquals(this, value))
                 return true;
index 3d386b7..ab98daf 100644 (file)
@@ -18,7 +18,7 @@ namespace System
             return SpanHelpers.IndexOf(
                 ref _firstChar,
                 Length,
-                ref value!._firstChar, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                ref value!._firstChar, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 value.Length) >= 0;
         }
 
index 60a82de..160ce4b 100644 (file)
@@ -6,6 +6,7 @@ using System.Buffers;
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -22,7 +23,7 @@ namespace System
 
     [Serializable]
     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-    public sealed partial class String : IComparable, IEnumerable, IConvertible, IEnumerable<char>, IComparable<string?>, IEquatable<string?>, ICloneable
+    public sealed partial class String : IComparable, IEnumerable, IConvertible, IEnumerable<char>, IComparable<string>, IEquatable<string>, ICloneable
     {
         /*
          * CONSTRUCTORS
@@ -436,7 +437,7 @@ namespace System
         }
 
         [NonVersionable]
-        public static bool IsNullOrEmpty(string? value)
+        public static bool IsNullOrEmpty([NotNullWhen(false)] string? value)
         {
             // Using 0u >= (uint)value.Length rather than
             // value.Length == 0 as it will elide the bounds check to
@@ -447,7 +448,7 @@ namespace System
             return (value == null || 0u >= (uint)value.Length) ? true : false;
         }
 
-        public static bool IsNullOrWhiteSpace(string? value)
+        public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value)
         {
             if (value == null) return true;
 
@@ -675,6 +676,7 @@ namespace System
             return length;
         }
 
+        [DoesNotReturn]
         private static void ThrowMustBeNullTerminatedString()
         {
             throw new ArgumentException(SR.Arg_MustBeNullTerminatedString);
index 83c81ae..ef7281f 100644 (file)
@@ -161,7 +161,9 @@ namespace System
 
         public abstract int Compare(string? x, string? y);
         public abstract bool Equals(string? x, string? y);
-        public abstract int GetHashCode(string? obj); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+#pragma warning disable CS8614 // Remove warning disable when nullable attributes are respected
+        public abstract int GetHashCode(string obj);
+#pragma warning restore CS8614
     }
 
     [Serializable]
@@ -214,7 +216,7 @@ namespace System
             return _compareInfo.Compare(x, y, _options) == 0;
         }
 
-        public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        public override int GetHashCode(string obj)
         {
             if (obj == null)
             {
@@ -291,7 +293,7 @@ namespace System
             return x.Equals(y);
         }
 
-        public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        public override int GetHashCode(string obj)
         {
             if (obj == null)
             {
@@ -300,10 +302,10 @@ namespace System
 
             if (_ignoreCase)
             {
-                return obj!.GetHashCodeOrdinalIgnoreCase(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                return obj!.GetHashCodeOrdinalIgnoreCase(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
-            return obj!.GetHashCode(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return obj!.GetHashCode(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         // Equals method for the comparer itself. 
@@ -334,13 +336,13 @@ namespace System
 
         public override bool Equals(string? x, string? y) => string.Equals(x, y);
 
-        public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        public override int GetHashCode(string obj)
         {
             if (obj == null)
             {
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
             }
-            return obj!.GetHashCode(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return obj!.GetHashCode(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public void GetObjectData(SerializationInfo info, StreamingContext context)
@@ -379,13 +381,13 @@ namespace System
             return CompareInfo.EqualsOrdinalIgnoreCase(ref x.GetRawStringData(), ref y.GetRawStringData(), x.Length);
         }
 
-        public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        public override int GetHashCode(string obj)
         {
             if (obj == null)
             {
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
             }
-            return obj!.GetHashCodeOrdinalIgnoreCase(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            return obj!.GetHashCodeOrdinalIgnoreCase(); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         public void GetObjectData(SerializationInfo info, StreamingContext context)
index 98f3061..9122641 100644 (file)
@@ -72,7 +72,7 @@ namespace System.Text
                     object o = new object();
                     Interlocked.CompareExchange<object?>(ref s_InternalSyncObject, o, null);
                 }
-                return s_InternalSyncObject!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return s_InternalSyncObject!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
index 338724c..3c1b360 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.Serialization;
 
@@ -73,6 +74,7 @@ namespace System.Text
             }
         }
 
+        [DoesNotReturn]
         private void Throw(byte[] bytesUnknown, int index)
         {
             bytesUnknown = bytesUnknown ?? Array.Empty<byte>();
index 4b4bcb6..aa3f65b 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Threading;
 
@@ -14,11 +15,11 @@ namespace System.Text
         private static DecoderFallback? s_exceptionFallback;
 
         public static DecoderFallback ReplacementFallback =>
-            s_replacementFallback ?? Interlocked.CompareExchange(ref s_replacementFallback, new DecoderReplacementFallback(), null) ?? s_replacementFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            s_replacementFallback ?? Interlocked.CompareExchange(ref s_replacementFallback, new DecoderReplacementFallback(), null) ?? s_replacementFallback!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
 
 
         public static DecoderFallback ExceptionFallback =>
-            s_exceptionFallback ?? Interlocked.CompareExchange<DecoderFallback?>(ref s_exceptionFallback, new DecoderExceptionFallback(), null) ?? s_exceptionFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            s_exceptionFallback ?? Interlocked.CompareExchange<DecoderFallback?>(ref s_exceptionFallback, new DecoderExceptionFallback(), null) ?? s_exceptionFallback!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
 
         // Fallback
         //
@@ -296,6 +297,7 @@ namespace System.Text
         }
 
         // private helper methods
+        [DoesNotReturn]
         internal void ThrowLastBytesRecursive(byte[] bytesUnknown)
         {
             bytesUnknown = bytesUnknown ?? Array.Empty<byte>();
index 7e627fd..5b0247a 100644 (file)
@@ -398,7 +398,6 @@ namespace System.Text
             // opportunity for any code before us to make forward progress, so we must fail immediately.
 
             _encoding.ThrowCharsOverflow(this, nothingDecoded: true);
-            // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
             throw null!; // will never reach this point
         }
 
index 57413ec..beb58e0 100644 (file)
@@ -109,7 +109,6 @@ namespace System.Text
         // Construction
         public DecoderReplacementFallbackBuffer(DecoderReplacementFallback fallback)
         {
-            // TODO-NULLABLE: NullReferenceException (fallback)
             _strDefault = fallback.DefaultString;
         }
 
index dddb1d5..518ceb7 100644 (file)
@@ -72,7 +72,7 @@ namespace System.Text
                     object o = new object();
                     Interlocked.CompareExchange<object?>(ref s_InternalSyncObject, o, null);
                 }
-                return s_InternalSyncObject!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return s_InternalSyncObject!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
index c3a03ab..8fa9e6d 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Buffers;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Text
@@ -22,7 +23,7 @@ namespace System.Text
                 if (s_replacementFallback == null)
                     Interlocked.CompareExchange<EncoderFallback?>(ref s_replacementFallback, new EncoderReplacementFallback(), null);
 
-                return s_replacementFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return s_replacementFallback!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -34,7 +35,7 @@ namespace System.Text
                 if (s_exceptionFallback == null)
                     Interlocked.CompareExchange<EncoderFallback?>(ref s_exceptionFallback, new EncoderExceptionFallback(), null);
 
-                return s_exceptionFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return s_exceptionFallback!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -376,6 +377,7 @@ namespace System.Text
         }
 
         // private helper methods
+        [DoesNotReturn]
         internal void ThrowLastCharRecursive(int charRecursive)
         {
             // Throw it, using our complete character
index e124e41..99f0fe9 100644 (file)
@@ -110,7 +110,6 @@ namespace System.Text
         // Construction
         public EncoderReplacementFallbackBuffer(EncoderReplacementFallback fallback)
         {
-            // TODO-NULLABLE: NullReferenceException
             // 2X in case we're a surrogate pair
             _strDefault = fallback.DefaultString + fallback.DefaultString;
         }
index ef7ba78..a1180a1 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Runtime.Serialization;
 
@@ -1181,6 +1182,7 @@ namespace System.Text
             return Array.Empty<char>();
         }
 
+        [DoesNotReturn]
         internal void ThrowBytesOverflow()
         {
             // Special message to include fallback type in case fallback's GetMaxCharCount is broken
@@ -1204,12 +1206,15 @@ namespace System.Text
             encoder!.ClearMustFlush();
         }
 
+        [DoesNotReturn]
         [StackTraceHidden]
         internal static void ThrowConversionOverflow()
         {
             throw new ArgumentException(SR.Argument_ConversionOverflow);
         }
 
+        [DoesNotReturn]
+        [StackTraceHidden]
         internal void ThrowCharsOverflow()
         {
             // Special message to include fallback type in case fallback's GetMaxCharCount is broken
index 8a9d2a5..01837fc 100644 (file)
@@ -6,7 +6,6 @@
 // https://github.com/dotnet/buildtools/blob/6736870b84e06b75e7df32bb84d442db1b2afa10/src/Microsoft.DotNet.Build.Tasks/PackageFiles/encoding.targets
 //
 
-// TODO-NULLABLE: We should edit original source instead: https://github.com/dotnet/buildtools/blob/master/src/Microsoft.DotNet.Build.Tasks/GenerateEncodingTable.cs#L235
 namespace System.Text
 {
     internal static partial class EncodingTable
index 6616227..4c0bd4a 100644 (file)
@@ -159,7 +159,7 @@ namespace System.Text
                     return null;
             }
 
-            CodePageDataItem? data = s_codePageToCodePageData![index]; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            CodePageDataItem? data = s_codePageToCodePageData![index]; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             if (data == null)
             {
                 Interlocked.CompareExchange<CodePageDataItem?>(ref s_codePageToCodePageData[index], InternalGetCodePageDataItem(codePage, index), null);
index ec9d2c4..e55e4a5 100644 (file)
@@ -637,7 +637,7 @@ namespace System.Text
                         ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
                     }
 
-                    return new ReadOnlyMemory<char>(_currentChunk!.m_ChunkChars, 0, _currentChunk.m_ChunkLength); // TODO-NULLABLE: https://github.com/dotnet/csharplang#538
+                    return new ReadOnlyMemory<char>(_currentChunk!.m_ChunkChars, 0, _currentChunk.m_ChunkLength); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 }
             }
 
@@ -1335,7 +1335,7 @@ namespace System.Text
 
             if (values[0] != null)
             {
-                Append(values[0]!.ToString()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                Append(values[0]!.ToString()); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             for (int i = 1; i < values.Length; i++)
@@ -1343,7 +1343,7 @@ namespace System.Text
                 Append(separator, separatorLength);
                 if (values[i] != null)
                 {
-                    Append(values[i]!.ToString()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                    Append(values[i]!.ToString()); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                 }
             }
             return this;
@@ -1905,9 +1905,9 @@ namespace System.Text
                     }
                     else if (replacementsCount >= replacements.Length)
                     {
-                        Array.Resize(ref replacements!, replacements.Length * 3 / 2 + 4); // Grow by ~1.5x, but more in the begining // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        Array.Resize(ref replacements!, replacements.Length * 3 / 2 + 4); // Grow by ~1.5x, but more in the begining // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     }
-                    replacements![replacementsCount++] = indexInChunk; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    replacements![replacementsCount++] = indexInChunk; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     indexInChunk += oldValue.Length;
                     count -= oldValue.Length;
                 }
index 99001f7..37c45db 100644 (file)
@@ -50,7 +50,7 @@ namespace System.Text
             return true;
         }
 
-        object? IEnumerator.Current => _current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
+        object? IEnumerator.Current => _current;
 
         void IDisposable.Dispose()
         {
index 1fc50d2..cc733ef 100644 (file)
@@ -519,7 +519,7 @@ namespace System.Text
 
                 // We mustn't have left over fallback data when not converting
                 if (encoder._throwOnOverflow && fallbackBuffer.Remaining > 0)
-                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback!.GetType())); // TODO-NULLABLE: NullReferenceException
+                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback?.GetType()));
             }
             else
             {
index 5a33c6d..89bd8c5 100644 (file)
@@ -138,7 +138,7 @@ namespace System.Text
                 ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
             }
 
-            if (chars!.Length - index < count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (chars!.Length - index < count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer);
             }
@@ -165,7 +165,7 @@ namespace System.Text
 
             fixed (char* pChars = chars)
             {
-                return GetByteCountCommon(pChars, chars!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                return GetByteCountCommon(pChars, chars!.Length); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
 
@@ -275,12 +275,12 @@ namespace System.Text
                     resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
             }
 
-            if (s!.Length - charIndex < charCount) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (s!.Length - charIndex < charCount) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.s, ExceptionResource.ArgumentOutOfRange_IndexCount);
             }
 
-            if ((uint)byteIndex > bytes!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if ((uint)byteIndex > bytes!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutOfRange_Index);
             }
@@ -325,12 +325,12 @@ namespace System.Text
                     resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
             }
 
-            if (chars!.Length - charIndex < charCount) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (chars!.Length - charIndex < charCount) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCount);
             }
 
-            if ((uint)byteIndex > bytes!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if ((uint)byteIndex > bytes!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutOfRange_Index);
             }
@@ -443,7 +443,7 @@ namespace System.Text
                 ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
             }
 
-            if (bytes!.Length - index < count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (bytes!.Length - index < count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer);
             }
@@ -510,12 +510,12 @@ namespace System.Text
                     resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
             }
 
-            if (bytes!.Length - byteIndex < byteCount) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (bytes!.Length - byteIndex < byteCount) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer);
             }
 
-            if ((uint)charIndex > (uint)chars!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if ((uint)charIndex > (uint)chars!.Length) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.charIndex, ExceptionResource.ArgumentOutOfRange_Index);
             }
@@ -672,7 +672,7 @@ namespace System.Text
                     resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
             }
 
-            if (bytes!.Length - index < count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (bytes!.Length - index < count) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer);
             }
index 7daf0cf..5c8a409 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Buffers;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -50,6 +51,7 @@ namespace System.Text.Unicode
         /// <paramref name="value"/> but where all invalid UTF-8 sequences have been replaced
         /// with U+FFD.
         /// </summary>
+        [return: NotNullIfNotNull("value")]
         public static Utf8String? ValidateAndFixupUtf8String(Utf8String? value)
         {
             if (Utf8String.IsNullOrEmpty(value))
index d541f65..f153f03 100644 (file)
@@ -390,7 +390,7 @@ namespace System.Text
                 {
                     fallbackBuffer = encoder.FallbackBuffer;
                     if (fallbackBuffer.Remaining > 0)
-                        throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback!.GetType())); // TODO-NULLABLE: NullReferenceException
+                        throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback?.GetType()));
 
                     // Set our internal fallback interesting things.
                     fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
@@ -679,7 +679,7 @@ namespace System.Text
                     // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
                     fallbackBuffer = encoder.FallbackBuffer;
                     if (fallbackBuffer.Remaining > 0 && encoder._throwOnOverflow)
-                        throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback!.GetType())); // TODO-NULLABLE: NullReferenceException
+                        throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback?.GetType()));
 
                     // Set our internal fallback interesting things.
                     fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
index 5c95e29..de7fc50 100644 (file)
@@ -83,9 +83,7 @@ namespace System.Text
             }
         }
 
-#pragma warning disable CS8609 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268
         public override string ToString()
-#pragma warning restore CS8609
         {
             var s = _chars.Slice(0, _pos).ToString();
             Dispose();
index a61af6d..cf279ac 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Threading
 {
@@ -56,12 +57,13 @@ namespace System.Threading
             m_valueChangedHandler = valueChangedHandler;
         }
 
+        [MaybeNull]
         public T Value
         {
             get
             {
                 object? obj = ExecutionContext.GetLocalValue(this);
-                return (obj == null) ? default! : (T)obj; // TODO-NULLABLE-GENERIC
+                return (obj == null) ? default! : (T)obj; // TODO-NULLABLE: Remove ! when nullable attributes are respected
             }
             set
             {
@@ -72,8 +74,8 @@ namespace System.Threading
         void IAsyncLocal.OnValueChanged(object? previousValueObj, object? currentValueObj, bool contextChanged)
         {
             Debug.Assert(m_valueChangedHandler != null);
-            T previousValue = previousValueObj == null ? default! : (T)previousValueObj; // TODO-NULLABLE-GENERIC
-            T currentValue = currentValueObj == null ? default! : (T)currentValueObj; // TODO-NULLABLE-GENERIC
+            T previousValue = previousValueObj == null ? default! : (T)previousValueObj;
+            T currentValue = currentValueObj == null ? default! : (T)currentValueObj;
             m_valueChangedHandler(new AsyncLocalValueChangedArgs<T>(previousValue, currentValue, contextChanged));
         }
     }
@@ -88,8 +90,8 @@ namespace System.Threading
 
     public readonly struct AsyncLocalValueChangedArgs<T>
     {
-        public T PreviousValue { get; }
-        public T CurrentValue { get; }
+        [MaybeNull] public T PreviousValue { get; }
+        [MaybeNull] public T CurrentValue { get; }
 
         //
         // If the value changed because we changed to a different ExecutionContext, this is true.  If it changed
@@ -97,7 +99,7 @@ namespace System.Threading
         //
         public bool ThreadContextChanged { get; }
 
-        internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged)
+        internal AsyncLocalValueChangedArgs([AllowNull] T previousValue, [AllowNull] T currentValue, bool contextChanged)
         {
             PreviousValue = previousValue;
             CurrentValue = currentValue;
index 769b4e0..42d54f6 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Threading
 {
@@ -348,6 +349,7 @@ namespace System.Threading
         }
 
         // Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
+        [DoesNotReturn]
         private void ThrowOperationCanceledException() =>
             throw new OperationCanceledException(SR.OperationCanceled, this);
     }
index 02ab1c4..4c17056 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading.Tasks;
 
 namespace System.Threading
@@ -132,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: https://github.com/dotnet/roslyn/issues/26761
+                    _kernelEvent!.Set(); // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
                 }
 
-                return _kernelEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return _kernelEvent!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -466,6 +467,7 @@ namespace System.Threading
         }
 
         /// <summary>Throws an <see cref="ObjectDisposedException"/>.  Separated out from ThrowIfDisposed to help with inlining.</summary>
+        [DoesNotReturn]
         private static void ThrowObjectDisposedException() =>
             throw new ObjectDisposedException(null, SR.CancellationTokenSource_Disposed);
 
index 7241d61..87971df 100644 (file)
@@ -76,7 +76,7 @@ namespace System.Threading
 
         public bool Reset()
         {
-            bool res = Interop.Kernel32.ResetEvent(SafeWaitHandle!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+            bool res = Interop.Kernel32.ResetEvent(SafeWaitHandle);
             if (!res)
                 throw Win32Marshal.GetExceptionForLastWin32Error();
             return res;
@@ -84,7 +84,7 @@ namespace System.Threading
         
         public bool Set()
         {
-            bool res = Interop.Kernel32.SetEvent(SafeWaitHandle!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+            bool res = Interop.Kernel32.SetEvent(SafeWaitHandle);
             if (!res)
                 throw Win32Marshal.GetExceptionForLastWin32Error();
             return res;
index bafa736..96c2ef8 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 
 namespace System.Threading
@@ -44,7 +45,7 @@ namespace System.Threading
             }
         }
 
-        public static bool TryOpenExisting(string name, out EventWaitHandle? result) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static bool TryOpenExisting(string name, [NotNullWhen(true)] out EventWaitHandle? result)
         {
             return OpenExistingWorker(name, out result) == OpenExistingResult.Success;
         }
index 64f2f18..c1cae56 100644 (file)
@@ -12,6 +12,7 @@
 ===========================================================*/
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.ExceptionServices;
 using System.Runtime.Serialization;
@@ -393,8 +394,8 @@ namespace System.Threading
                 if (previousChangeNotifications != null && nextChangeNotifications != null)
                 {
                     // Notifications can't exist without values
-                    Debug.Assert(previousExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
-                    Debug.Assert(nextExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                    Debug.Assert(previousExecutionCtx!.m_localValues != null);
+                    Debug.Assert(nextExecutionCtx!.m_localValues != null);
                     // Both contexts have change notifications, check previousExecutionCtx first
                     foreach (IAsyncLocal local in previousChangeNotifications)
                     {
@@ -428,7 +429,7 @@ namespace System.Threading
                 else if (previousChangeNotifications != null)
                 {
                     // Notifications can't exist without values
-                    Debug.Assert(previousExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                    Debug.Assert(previousExecutionCtx!.m_localValues != null);
                     // No current values, so just check previous against null
                     foreach (IAsyncLocal local in previousChangeNotifications)
                     {
@@ -442,9 +443,9 @@ namespace System.Threading
                 else // Implied: nextChangeNotifications != null
                 {
                     // Notifications can't exist without values
-                    Debug.Assert(nextExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                    Debug.Assert(nextExecutionCtx!.m_localValues != null);
                     // No previous values, so just check current against null
-                    foreach (IAsyncLocal local in nextChangeNotifications!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388
+                    foreach (IAsyncLocal local in nextChangeNotifications!)
                     {
                         nextExecutionCtx.m_localValues.TryGetValue(local, out object? currentValue);
                         if (currentValue != null)
@@ -462,6 +463,7 @@ namespace System.Threading
             }
         }
 
+        [DoesNotReturn]
         [StackTraceHidden]
         private static void ThrowNullContext()
         {
@@ -544,7 +546,7 @@ namespace System.Threading
                 {
                     int newNotificationIndex = newChangeNotifications.Length;
                     Array.Resize(ref newChangeNotifications, newNotificationIndex + 1);
-                    newChangeNotifications![newNotificationIndex] = local; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    newChangeNotifications![newNotificationIndex] = local; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 }
             }
 
index 5ae8415..51e45c1 100644 (file)
@@ -9,6 +9,7 @@
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Threading
 {
@@ -47,7 +48,7 @@ namespace System.Threading
         /// if an object was not used and to then dispose of the object appropriately.
         /// </para>
         /// </remarks>
-        public static T EnsureInitialized<T>(ref T target) where T : class? =>
+        public static T EnsureInitialized<T>([AllowNull] ref T target) where T : class =>
             Volatile.Read(ref target) ?? EnsureInitializedCore(ref target);
 
         /// <summary>
@@ -56,11 +57,11 @@ namespace System.Threading
         /// <typeparam name="T">The reference type of the reference to be initialized.</typeparam>
         /// <param name="target">The variable that need to be initialized</param>
         /// <returns>The initialized variable</returns>
-        private static T EnsureInitializedCore<T>(ref T target) where T : class?
+        private static T EnsureInitializedCore<T>([AllowNull] ref T target) where T : class
         {
             try
             {
-                Interlocked.CompareExchange(ref target, Activator.CreateInstance<T>(), null!); // TODO-NULLABLE-GENERIC
+                Interlocked.CompareExchange(ref target, Activator.CreateInstance<T>(), null!);
             }
             catch (MissingMethodException)
             {
@@ -99,7 +100,7 @@ namespace System.Threading
         /// if an object was not used and to then dispose of the object appropriately.
         /// </para>
         /// </remarks>
-        public static T EnsureInitialized<T>(ref T target, Func<T> valueFactory) where T : class? =>
+        public static T EnsureInitialized<T>([AllowNull] ref T target, Func<T> valueFactory) where T : class =>
             Volatile.Read(ref target) ?? EnsureInitializedCore(ref target, valueFactory);
 
         /// <summary>
@@ -109,7 +110,7 @@ namespace System.Threading
         /// <param name="target">The variable that need to be initialized</param>
         /// <param name="valueFactory">The delegate that will be executed to initialize the target</param>
         /// <returns>The initialized variable</returns>
-        private static T EnsureInitializedCore<T>(ref T target, Func<T> valueFactory) where T : class?
+        private static T EnsureInitializedCore<T>([AllowNull] ref T target, Func<T> valueFactory) where T : class
         {
             T value = valueFactory();
             if (value == null)
@@ -117,7 +118,7 @@ namespace System.Threading
                 throw new InvalidOperationException(SR.Lazy_StaticInit_InvalidOperation);
             }
 
-            Interlocked.CompareExchange(ref target, value, null!); // TODO-NULLABLE-GENERIC
+            Interlocked.CompareExchange(ref target, value, null!);
             Debug.Assert(target != null);
             return target;
         }
@@ -134,7 +135,7 @@ namespace System.Threading
         /// <param name="syncLock">A reference to an object used as the mutually exclusive lock for initializing
         /// <paramref name="target"/>. If <paramref name="syncLock"/> is null, a new object will be instantiated.</param>
         /// <returns>The initialized value of type <typeparamref name="T"/>.</returns>
-        public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object? syncLock)
+        public static T EnsureInitialized<T>([AllowNull] ref T target, ref bool initialized, ref object? syncLock)
         {
             // Fast path.
             if (Volatile.Read(ref initialized))
@@ -156,7 +157,7 @@ namespace System.Threading
         /// a new object will be instantiated.
         /// </param>
         /// <returns>The initialized object.</returns>
-        private static T EnsureInitializedCore<T>(ref T target, ref bool initialized, ref object? syncLock)
+        private static T EnsureInitializedCore<T>([AllowNull] ref T target, ref bool initialized, ref object? syncLock)
         {
             // Lazily initialize the lock if necessary and then double check if initialization is still required.
             lock (EnsureLockInitialized(ref syncLock))
@@ -193,7 +194,7 @@ namespace System.Threading
         /// <param name="valueFactory">The <see cref="T:System.Func{T}"/> invoked to initialize the
         /// reference or value.</param>
         /// <returns>The initialized value of type <typeparamref name="T"/>.</returns>
-        public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object? syncLock, Func<T> valueFactory)
+        public static T EnsureInitialized<T>([AllowNull] ref T target, ref bool initialized, ref object? syncLock, Func<T> valueFactory)
         {
             // Fast path.
             if (Volatile.Read(ref initialized))
@@ -217,7 +218,7 @@ namespace System.Threading
         /// The <see cref="T:System.Func{T}"/> to invoke in order to produce the lazily-initialized value.
         /// </param>
         /// <returns>The initialized object.</returns>
-        private static T EnsureInitializedCore<T>(ref T target, ref bool initialized, ref object? syncLock, Func<T> valueFactory)
+        private static T EnsureInitializedCore<T>([AllowNull] ref T target, ref bool initialized, ref object? syncLock, Func<T> valueFactory)
         {
             // Lazily initialize the lock if necessary and then double check if initialization is still required.
             lock (EnsureLockInitialized(ref syncLock))
@@ -241,7 +242,7 @@ namespace System.Threading
         /// <paramref name="target"/>. If <paramref name="syncLock"/> is null, a new object will be instantiated.</param>
         /// <param name="valueFactory">The <see cref="T:System.Func{T}"/> invoked to initialize the reference.</param>
         /// <returns>The initialized value of type <typeparamref name="T"/>.</returns>
-        public static T EnsureInitialized<T>(ref T target, ref object? syncLock, Func<T> valueFactory) where T : class? =>
+        public static T EnsureInitialized<T>([AllowNull] ref T target, ref object? syncLock, Func<T> valueFactory) where T : class =>
             Volatile.Read(ref target) ?? EnsureInitializedCore(ref target, ref syncLock, valueFactory);
 
         /// <summary>
@@ -256,7 +257,7 @@ namespace System.Threading
         /// The <see cref="T:System.Func{T}"/> to invoke in order to produce the lazily-initialized value.
         /// </param>
         /// <returns>The initialized object.</returns>
-        private static T EnsureInitializedCore<T>(ref T target, ref object? syncLock, Func<T> valueFactory) where T : class?
+        private static T EnsureInitializedCore<T>([AllowNull] ref T target, ref object? syncLock, Func<T> valueFactory) where T : class
         {
             // Lazily initialize the lock if necessary and then double check if initialization is still required.
             lock (EnsureLockInitialized(ref syncLock))
@@ -283,6 +284,6 @@ namespace System.Threading
         private static object EnsureLockInitialized(ref object? syncLock) =>
             syncLock ??
             Interlocked.CompareExchange(ref syncLock, new object(), null) ??
-            syncLock!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            syncLock!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
     }
 }
index 6d89a5e..7226538 100644 (file)
@@ -88,7 +88,7 @@ namespace System.Threading
         // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001).
         public void ReleaseMutex()
         {
-            if (!Interop.Kernel32.ReleaseMutex(SafeWaitHandle!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+            if (!Interop.Kernel32.ReleaseMutex(SafeWaitHandle))
             {
                 throw new ApplicationException(SR.Arg_SynchronizationLockException);
             }
index 50cd42a..2d8313c 100644 (file)
@@ -2,11 +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.IO;
 using Microsoft.Win32;
 using Microsoft.Win32.SafeHandles;
-using System.Runtime.InteropServices;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Runtime.InteropServices;
 
 namespace System.Threading
 {
@@ -57,7 +58,7 @@ namespace System.Threading
             }
         }
 
-        public static bool TryOpenExisting(string name, out Mutex? result) => // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static bool TryOpenExisting(string name, [NotNullWhen(true)] out Mutex? result) =>
             OpenExistingWorker(name, out result) == OpenExistingResult.Success;
     }
 }
index f05ef52..47f26ef 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics; // for TraceInformation
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 
 namespace System.Threading
@@ -195,7 +196,7 @@ namespace System.Threading
         /// could not be found.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private ReaderWriterCount? GetThreadRWCount(bool dontAllocate) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        private ReaderWriterCount? GetThreadRWCount(bool dontAllocate)
         {
             ReaderWriterCount? rwc = t_rwc;
             ReaderWriterCount? empty = null;
@@ -318,7 +319,7 @@ namespace System.Threading
 
                 _spinLock.Enter(EnterSpinLockReason.EnterAnyRead);
 
-                lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                lrwc = GetThreadRWCount(dontAllocate: false)!;
 
                 //Check if the reader lock is already acquired. Note, we could
                 //check the presence of a reader by not allocating rwc (But that 
@@ -343,7 +344,7 @@ namespace System.Threading
             else
             {
                 _spinLock.Enter(EnterSpinLockReason.EnterAnyRead);
-                lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                lrwc = GetThreadRWCount(dontAllocate: false)!;
                 if (lrwc.readercount > 0)
                 {
                     lrwc.readercount++;
@@ -401,7 +402,7 @@ namespace System.Threading
                     _spinLock.Enter(EnterSpinLockReason.EnterAnyRead);
                     //The per-thread structure may have been recycled as the lock is acquired (due to message pumping), load again.
                     if (IsRwHashEntryChanged(lrwc))
-                        lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        lrwc = GetThreadRWCount(dontAllocate: false)!;
                     continue;
                 }
 
@@ -410,7 +411,7 @@ namespace System.Threading
                 {
                     LazyCreateEvent(ref _readEvent, EnterLockType.Read);
                     if (IsRwHashEntryChanged(lrwc))
-                        lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        lrwc = GetThreadRWCount(dontAllocate: false)!;
                     continue;   // since we left the lock, start over. 
                 }
 
@@ -420,7 +421,7 @@ namespace System.Threading
                     return false;
                 }
                 if (IsRwHashEntryChanged(lrwc))
-                    lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    lrwc = GetThreadRWCount(dontAllocate: false)!;
             }
 
             _spinLock.Exit();
@@ -502,7 +503,7 @@ namespace System.Threading
                 }
                 _spinLock.Enter(enterMyLockReason);
 
-                lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                lrwc = GetThreadRWCount(dontAllocate: false)!;
 
                 if (id == _writeLockOwnerId)
                 {
@@ -555,7 +556,7 @@ namespace System.Threading
                         if (lrwc != null)
                         {
                             if (IsRwHashEntryChanged(lrwc))
-                                lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                                lrwc = GetThreadRWCount(dontAllocate: false)!;
 
                             if (lrwc.readercount > 0)
                             {
@@ -624,7 +625,7 @@ namespace System.Threading
             {
                 Debug.Assert(lrwc != null, "Initialized based on _fIsReentrant earlier in the method");
                 if (IsRwHashEntryChanged(lrwc))
-                    lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    lrwc = GetThreadRWCount(dontAllocate: false)!;
                 lrwc.writercount++;
             }
 
@@ -688,7 +689,7 @@ namespace System.Threading
             else
             {
                 _spinLock.Enter(EnterSpinLockReason.EnterAnyRead);
-                lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                lrwc = GetThreadRWCount(dontAllocate: false)!;
 
                 if (id == _upgradeLockOwnerId)
                 {
@@ -767,7 +768,7 @@ namespace System.Threading
                 //thread did not grab the entry.
                 Debug.Assert(lrwc != null, "Initialized based on _fIsReentrant earlier in the method");
                 if (IsRwHashEntryChanged(lrwc))
-                    lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    lrwc = GetThreadRWCount(dontAllocate: false)!;
                 lrwc.upgradecount++;
             }
 
@@ -829,7 +830,7 @@ namespace System.Threading
             else
             {
                 _spinLock.Enter(EnterSpinLockReason.ExitAnyWrite);
-                lrwc = GetThreadRWCount(dontAllocate: false)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                lrwc = GetThreadRWCount(dontAllocate: false)!;
 
                 if (lrwc == null)
                 {
@@ -913,7 +914,7 @@ namespace System.Threading
         /// while holding a spin lock).  If all goes well, reenter the lock and
         /// set 'waitEvent' 
         /// </summary>
-        private void LazyCreateEvent(ref EventWaitHandle? waitEvent, EnterLockType enterLockType) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        private void LazyCreateEvent([NotNull] ref EventWaitHandle? waitEvent, EnterLockType enterLockType)
         {
 #if DEBUG
             Debug.Assert(_spinLock.IsHeld);
index a87405f..f012274 100644 (file)
@@ -5,6 +5,7 @@
 using Microsoft.Win32;
 using Microsoft.Win32.SafeHandles;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Runtime.InteropServices;
 
@@ -52,7 +53,7 @@ namespace System.Threading
             }
         }
 
-        public static bool TryOpenExisting(string name, out Semaphore? result) => // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static bool TryOpenExisting(string name, [NotNullWhen(true)] out Semaphore? result) =>
             OpenExistingWorker(name, out result) == OpenExistingResult.Success;
 
         public int Release() => ReleaseCore(1);
index 9065ae1..50014bf 100644 (file)
@@ -152,7 +152,11 @@ namespace System.Threading.Tasks
         private CompletionState EnsureCompletionStateInitialized()
         {
             // ValueLock not needed, but it's ok if it's held
-            return LazyInitializer.EnsureInitialized<CompletionState>(ref m_completionState!, () => new CompletionState()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
+#pragma warning disable CS8603 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
+            return LazyInitializer.EnsureInitialized(ref m_completionState!, () => new CompletionState());
+#pragma warning restore CS8603
+#pragma warning restore CS8634
         }
 
         /// <summary>Gets whether completion has been requested.</summary>
@@ -297,7 +301,7 @@ namespace System.Threading.Tasks
                     {
                         try
                         {
-                            processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessExclusiveTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessExclusiveTasks(), this,
                                 default, GetCreationOptionsForTask(fairly));
                             processingTask.Start(m_underlyingTaskScheduler);
                             // When we call Start, if the underlying scheduler throws in QueueTask, TPL will fault the task and rethrow
@@ -327,7 +331,7 @@ namespace System.Threading.Tasks
                             {
                                 try
                                 {
-                                    processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessConcurrentTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                                    processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessConcurrentTasks(), this,
                                         default, GetCreationOptionsForTask(fairly));
                                     processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew
                                 }
index c82372c..1a7899d 100644 (file)
@@ -12,6 +12,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.ExceptionServices;
 
@@ -60,7 +61,8 @@ namespace System.Threading.Tasks
     [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
     public class Task<TResult> : Task
     {
-        internal TResult m_result = default!; // The value itself, if set. // TODO-NULLABLE-GENERIC
+        // The value itself, if set.
+        [MaybeNull] internal TResult m_result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
         private static readonly TaskFactory<TResult> s_Factory = new TaskFactory<TResult>();
 
@@ -95,7 +97,7 @@ namespace System.Threading.Tasks
             m_result = result;
         }
 
-        internal Task(bool canceled, TResult result, TaskCreationOptions creationOptions, CancellationToken ct)
+        internal Task(bool canceled, [AllowNull] TResult result, TaskCreationOptions creationOptions, CancellationToken ct)
             : base(canceled, creationOptions, ct)
         {
             if (!canceled)
@@ -209,7 +211,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentException">
         /// The <paramref name="function"/> argument is null.
         /// </exception>
-        public Task(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Func<object?, TResult> function, object? state)
             : this(function, state, null, default,
                 TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
@@ -230,7 +232,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
         /// has already been disposed.
         /// </exception>
-        public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken)
             : this(function, state, null, cancellationToken,
                     TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
@@ -255,7 +257,7 @@ namespace System.Threading.Tasks
         /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
         /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
         /// </exception>
-        public Task(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions)
             : this(function, state, Task.InternalCurrentIfAttached(creationOptions), default,
                     creationOptions, InternalTaskOptions.None, null)
         {
@@ -285,7 +287,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
         /// has already been disposed.
         /// </exception>
-        public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
             : this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
                     creationOptions, InternalTaskOptions.None, null)
         {
@@ -337,7 +339,7 @@ namespace System.Threading.Tasks
             }
 
             // Create and schedule the future.
-            Task<TResult> f = new Task<TResult>(function!, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Task<TResult> f = new Task<TResult>(function!, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             f.ScheduleAndStart(false);
             return f;
@@ -357,7 +359,7 @@ namespace System.Threading.Tasks
             }
 
             // Create and schedule the future.
-            Task<TResult> f = new Task<TResult>(function!, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Task<TResult> f = new Task<TResult>(function!, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             f.ScheduleAndStart(false);
             return f;
@@ -383,7 +385,7 @@ namespace System.Threading.Tasks
 
 
         // internal helper function breaks out logic used by TaskCompletionSource
-        internal bool TrySetResult(TResult result)
+        internal bool TrySetResult([AllowNull] TResult result)
         {
             Debug.Assert(m_action == null, "Task<T>.TrySetResult(): non-null m_action");
 
@@ -725,13 +727,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
-                this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationAction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationTask;
         }
@@ -756,7 +758,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="continuationAction"/> argument is null.
         /// </exception>
-        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state)
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
         }
@@ -783,7 +785,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
         /// has already been disposed.
         /// </exception>
-        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken)
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
         }
@@ -812,7 +814,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="scheduler"/> argument is null.
         /// </exception>
-        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler)
         {
             return ContinueWith(continuationAction, state, scheduler, default, TaskContinuationOptions.None);
         }
@@ -846,7 +848,7 @@ namespace System.Threading.Tasks
         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
         /// </exception>
-        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions)
         {
             return ContinueWith(continuationAction, state, TaskScheduler.Current, default, continuationOptions);
         }
@@ -890,14 +892,14 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
         /// has already been disposed.
         /// </exception>
-        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken,
                                  TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
         {
             return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
         }
 
         // Same as the above overload, only with a stack mark.
-        internal Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        internal Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler, CancellationToken cancellationToken,
                                    TaskContinuationOptions continuationOptions)
         {
             if (continuationAction == null)
@@ -918,13 +920,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
-                this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationAction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationTask;
         }
@@ -1134,13 +1136,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
-                this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationFunction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationFuture;
         }
@@ -1357,13 +1359,13 @@ namespace System.Threading.Tasks
                 out internalOptions);
 
             Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
-                this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationFunction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationFuture;
         }
@@ -1384,7 +1386,7 @@ namespace System.Threading.Tasks
             m_task = task;
         }
 
-        public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default!; } } // TODO-NULLABLE-GENERIC
+        [MaybeNull] public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default!; } }
         public object? AsyncState { get { return m_task.AsyncState; } }
         public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
         public Exception? Exception { get { return m_task.Exception; } }
index e8be5bd..139e32f 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Threading.Tasks
 {
@@ -376,7 +377,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state)
         {
             Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -405,7 +406,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken)
         {
             Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
@@ -436,7 +437,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions)
         {
             Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -478,7 +479,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
         {
             return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
                 creationOptions, InternalTaskOptions.None, scheduler);
@@ -500,7 +501,7 @@ namespace System.Threading.Tasks
 
             Exception? ex = null;
             OperationCanceledException? oce = null;
-            TResult result = default!; // TODO-NULLABLE-GENERIC
+            TResult result = default!;
 
             try
             {
@@ -671,9 +672,9 @@ namespace System.Threading.Tasks
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(t);
 
-            if (asyncResult!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (asyncResult!.IsCompleted) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
-                try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
             }
             else
@@ -682,7 +683,7 @@ namespace System.Threading.Tasks
                     asyncResult.AsyncWaitHandle,
                     delegate
                     {
-                        try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                        try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                         catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
                     },
                     null,
@@ -712,7 +713,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> FromAsync(
             Func<AsyncCallback, object?, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Func<IAsyncResult, TResult> endMethod, object? state)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
         }
@@ -741,7 +742,7 @@ namespace System.Threading.Tasks
         /// </remarks>
         public Task<TResult> FromAsync(
             Func<AsyncCallback, object?, IAsyncResult> beginMethod,
-            Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
         }
@@ -765,7 +766,7 @@ namespace System.Threading.Tasks
             Task<TResult> promise = new Task<TResult>(state, creationOptions);
 
             if (AsyncCausalityTracer.LoggingOn)
-                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -773,7 +774,7 @@ namespace System.Threading.Tasks
             try
             {
                 //if we don't require synchronization, a faster set result path is taken
-                var asyncResult = beginMethod!(iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                var asyncResult = beginMethod!(iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -824,7 +825,7 @@ namespace System.Threading.Tasks
         public Task<TResult> FromAsync<TArg1>(
             Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            TArg1 arg1, object? state)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
         }
@@ -858,7 +859,7 @@ namespace System.Threading.Tasks
         public Task<TResult> FromAsync<TArg1>(
             Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            TArg1 arg1, object? state, TaskCreationOptions creationOptions)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
         }
@@ -882,7 +883,7 @@ namespace System.Threading.Tasks
             Task<TResult> promise = new Task<TResult>(state, creationOptions);
 
             if (AsyncCausalityTracer.LoggingOn)
-                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -890,7 +891,7 @@ namespace System.Threading.Tasks
             try
             {
                 //if we don't require synchronization, a faster set result path is taken
-                var asyncResult = beginMethod!(arg1, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                var asyncResult = beginMethod!(arg1, iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -945,7 +946,7 @@ namespace System.Threading.Tasks
         public Task<TResult> FromAsync<TArg1, TArg2>(
             Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, TArg2 arg2, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            TArg1 arg1, TArg2 arg2, object? state)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
         }
@@ -983,7 +984,7 @@ namespace System.Threading.Tasks
         public Task<TResult> FromAsync<TArg1, TArg2>(
             Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult> endMethod,
-            TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions)
         {
             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
         }
@@ -992,7 +993,7 @@ namespace System.Threading.Tasks
         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
         internal static Task<TResult> FromAsyncImpl<TArg1, TArg2>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
             Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
-            TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions)
         {
             if (beginMethod == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -1007,7 +1008,7 @@ namespace System.Threading.Tasks
             Task<TResult> promise = new Task<TResult>(state, creationOptions);
 
             if (AsyncCausalityTracer.LoggingOn)
-                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -1015,7 +1016,7 @@ namespace System.Threading.Tasks
             try
             {
                 //if we don't require synchronization, a faster set result path is taken
-                var asyncResult = beginMethod!(arg1, arg2, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                var asyncResult = beginMethod!(arg1, arg2, iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -1140,7 +1141,7 @@ namespace System.Threading.Tasks
             Task<TResult> promise = new Task<TResult>(state, creationOptions);
 
             if (AsyncCausalityTracer.LoggingOn)
-                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             if (Task.s_asyncDebuggingEnabled)
                 Task.AddToActiveTasks(promise);
@@ -1148,7 +1149,7 @@ namespace System.Threading.Tasks
             try
             {
                 //if we don't require synchronization, a faster set result path is taken
-                var asyncResult = beginMethod!(arg1, arg2, arg3, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                var asyncResult = beginMethod!(arg1, arg2, arg3, iar => // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     if (!iar.CompletedSynchronously)
                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -1228,7 +1229,7 @@ namespace System.Threading.Tasks
             internal static readonly AsyncCallback s_completeFromAsyncResult = CompleteFromAsyncResult;
 
             /// <summary>A reference to the object on which the begin/end methods are invoked.</summary>
-            private TInstance m_thisRef;
+            [AllowNull, MaybeNull] private TInstance m_thisRef;
             /// <summary>The end method.</summary>
             private Func<TInstance, IAsyncResult, TResult>? m_endMethod;
 
@@ -1253,13 +1254,13 @@ namespace System.Threading.Tasks
                 // Validate argument
                 if (asyncResult == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult);
 
-                var promise = asyncResult!.AsyncState as FromAsyncTrimPromise<TInstance>; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                var promise = asyncResult!.AsyncState as FromAsyncTrimPromise<TInstance>; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 if (promise == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
 
                 // Grab the relevant state and then null it out so that the task doesn't hold onto the state unnecessarily
-                var thisRef = promise!.m_thisRef; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                var thisRef = promise!.m_thisRef; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 var endMethod = promise.m_endMethod;
-                promise.m_thisRef = default!; // TODO-NULLABLE-GENERIC
+                promise.m_thisRef = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 promise.m_endMethod = null;
                 if (endMethod == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
 
@@ -1267,7 +1268,7 @@ namespace System.Threading.Tasks
                 // we'll instead complete the promise at the call site.
                 if (!asyncResult.CompletedSynchronously)
                 {
-                    promise.Complete(thisRef, endMethod!, asyncResult, requiresSynchronization: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    promise.Complete(thisRef, endMethod!, asyncResult, requiresSynchronization: true); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 }
             }
 
@@ -1322,7 +1323,7 @@ namespace System.Threading.Tasks
         {
             TaskCreationOptions tco;
             Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out _);
-            return new Task<TResult>(true, default!, tco, ct); // TODO-NULLABLE-GENERIC
+            return new Task<TResult>(true, default!, tco, ct); // TODO-NULLABLE: Remove ! when nullable attributes are respected
         }
 
         //
@@ -1610,7 +1611,7 @@ namespace System.Threading.Tasks
             if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
 
             // Check tasks array and make defensive copy
-            Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             // Bail early if cancellation has been requested.
             if (cancellationToken.IsCancellationRequested
@@ -1629,7 +1630,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                    // use a cached delegate
                    GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
-                   continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                   continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             else
             {
@@ -1638,7 +1639,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                    // use a cached delegate
                    GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
-                   continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                   continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
 
@@ -1656,7 +1657,7 @@ namespace System.Threading.Tasks
             if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
 
             // Check tasks array and make defensive copy
-            Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             // Bail early if cancellation has been requested.
             if (cancellationToken.IsCancellationRequested
@@ -1682,7 +1683,7 @@ namespace System.Threading.Tasks
                         Debug.Assert(state is Func<Task[], TResult>);
                         return ((Func<Task[], TResult>)state)(completedTasks.Result);
                     },
-                    continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             else
             {
@@ -1695,9 +1696,9 @@ namespace System.Threading.Tasks
                    {
                        completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
                         Debug.Assert(state is Action<Task[]>);
-                       ((Action<Task[]>)state)(completedTasks.Result); return default!; // TODO-NULLABLE-GENERIC
+                       ((Action<Task[]>)state)(completedTasks.Result); return default!;
                    },
-                   continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                   continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
 
@@ -1980,7 +1981,7 @@ namespace System.Threading.Tasks
             // check arguments
             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
-            if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
             Debug.Assert((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
@@ -2008,7 +2009,7 @@ namespace System.Threading.Tasks
                          Debug.Assert(state is Func<Task, TResult>);
                          return ((Func<Task, TResult>)state)(completedTask.Result);
                      },
-                     continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                     continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             else
             {
@@ -2020,9 +2021,9 @@ namespace System.Threading.Tasks
                     {
                         Debug.Assert(state is Action<Task>);
                         ((Action<Task>)state)(completedTask.Result);
-                        return default!; // TODO-NULLABLE-GENERIC
+                        return default!;
                     },
-                    continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
 
@@ -2036,7 +2037,7 @@ namespace System.Threading.Tasks
             // check arguments
             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
-            if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
             Debug.Assert((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
             if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
@@ -2058,7 +2059,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                     // Use a cached delegate
                     GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
-                    continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
             else
             {
@@ -2066,7 +2067,7 @@ namespace System.Threading.Tasks
                 return starter.ContinueWith<TResult>(
                     // Use a cached delegate
                     GenericDelegateCache<TAntecedentResult, TResult>.CWAnyActionDelegate,
-                    continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
         }
     }
@@ -2094,7 +2095,7 @@ namespace System.Threading.Tasks
                 var action = (Action<Task<TAntecedentResult>>)state;
                 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
                 action(arg);
-                return default!; // TODO-NULLABLE-GENERIC
+                return default!;
             };
 
         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationFunction)
@@ -2115,7 +2116,7 @@ namespace System.Threading.Tasks
                 Debug.Assert(state is Action<Task<TAntecedentResult>[]>);
                 var action = (Action<Task<TAntecedentResult>[]>)state;
                 action(wrappedAntecedents.Result);
-                return default!; // TODO-NULLABLE-GENERIC
+                return default!;
             };
     }
 }
index 157ad5d..9fa82ed 100644 (file)
@@ -25,6 +25,7 @@ using System.Collections;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 
 namespace System.Threading.Tasks
@@ -42,7 +43,7 @@ namespace System.Threading.Tasks
         /// <param name="result">The dequeued item.</param>
         /// <returns>true if an item could be dequeued; otherwise, false.</returns>
         /// <remarks>This method is meant to be thread-safe subject to the particular nature of the implementation.</remarks>
-        bool TryDequeue(out T result);
+        bool TryDequeue([MaybeNullWhen(false)] out T result);
 
         /// <summary>Gets whether the collection is currently empty.</summary>
         /// <remarks>This method may or may not be thread-safe.</remarks>
@@ -67,7 +68,7 @@ namespace System.Threading.Tasks
         /// <summary>Attempts to dequeue an item from the queue.</summary>
         /// <param name="result">The dequeued item.</param>
         /// <returns>true if an item could be dequeued; otherwise, false.</returns>
-        bool IProducerConsumerQueue<T>.TryDequeue(out T result) { return base.TryDequeue(out result); }
+        bool IProducerConsumerQueue<T>.TryDequeue([MaybeNullWhen(false)] out T result) { return base.TryDequeue(out result); }
 
         /// <summary>Gets whether the collection is currently empty.</summary>
         bool IProducerConsumerQueue<T>.IsEmpty { get { return base.IsEmpty; } }
@@ -194,7 +195,7 @@ namespace System.Threading.Tasks
         /// <summary>Attempts to dequeue an item from the queue.</summary>
         /// <param name="result">The dequeued item.</param>
         /// <returns>true if an item could be dequeued; otherwise, false.</returns>
-        public bool TryDequeue(out T result)
+        public bool TryDequeue([MaybeNullWhen(false)] out T result)
         {
             Segment segment = m_head;
             var array = segment.m_array;
@@ -204,7 +205,7 @@ namespace System.Threading.Tasks
             if (first != segment.m_state.m_lastCopy)
             {
                 result = array[first];
-                array[first] = default!; // Clear the slot to release the element  // TODO-NULLABLE-GENERIC
+                array[first] = default!; // Clear the slot to release the element
                 segment.m_state.m_first = (first + 1) & (array.Length - 1);
                 return true;
             }
@@ -217,7 +218,7 @@ namespace System.Threading.Tasks
         /// <param name="segment">The segment from which the item was dequeued.</param>
         /// <param name="result">The dequeued item.</param>
         /// <returns>true if an item could be dequeued; otherwise, false.</returns>
-        private bool TryDequeueSlow(ref Segment segment, ref T[] array, out T result)
+        private bool TryDequeueSlow(ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
         {
             Debug.Assert(segment != null, "Expected a non-null segment.");
             Debug.Assert(array != null, "Expected a non-null item array.");
@@ -239,12 +240,12 @@ namespace System.Threading.Tasks
 
             if (first == segment.m_state.m_last)
             {
-                result = default!; // TODO-NULLABLE-GENERIC
+                result = default!;
                 return false;
             }
 
             result = array[first];
-            array[first] = default!; // Clear the slot to release the element  // TODO-NULLABLE-GENERIC
+            array[first] = default!; // Clear the slot to release the element
             segment.m_state.m_first = (first + 1) & (segment.m_array.Length - 1);
             segment.m_state.m_lastCopy = segment.m_state.m_last; // Refresh m_lastCopy to ensure that m_first has not passed m_lastCopy
 
index 8f46037..5f071b2 100644 (file)
@@ -53,7 +53,7 @@ namespace System.Threading.Tasks.Sources
         /// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
         /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
         /// <param name="flags">The flags describing the behavior of the continuation.</param>
-        void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags);
 
         /// <summary>Gets the result of the <see cref="IValueTaskSource"/>.</summary>
         /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
@@ -73,7 +73,7 @@ namespace System.Threading.Tasks.Sources
         /// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
         /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
         /// <param name="flags">The flags describing the behavior of the continuation.</param>
-        void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags);
 
         /// <summary>Gets the result of the <see cref="IValueTaskSource{TResult}"/>.</summary>
         /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
index fd68a49..e72328a 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.ExceptionServices;
 using System.Runtime.InteropServices;
 
@@ -31,7 +32,7 @@ namespace System.Threading.Tasks.Sources
         /// <summary>Whether the current operation has completed.</summary>
         private bool _completed;
         /// <summary>The result with which the operation succeeded, or the default value if it hasn't yet completed or failed.</summary>
-        private TResult _result;
+        [AllowNull, MaybeNull] private TResult _result;
         /// <summary>The exception with which the operation failed, or null if it hasn't yet completed or completed successfully.</summary>
         private ExceptionDispatchInfo? _error;
         /// <summary>The current version of this value, used to help prevent misuse.</summary>
@@ -47,7 +48,7 @@ namespace System.Threading.Tasks.Sources
             // Reset/update state for the next use/await of this instance.
             _version++;
             _completed = false;
-            _result = default!; // TODO-NULLABLE-GENERIC
+            _result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
             _error = null;
             _executionContext = null;
             _capturedContext = null;
@@ -106,7 +107,7 @@ namespace System.Threading.Tasks.Sources
         /// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
         /// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
         /// <param name="flags">The flags describing the behavior of the continuation.</param>
-        public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
         {
             if (continuation == null)
             {
@@ -175,7 +176,7 @@ namespace System.Threading.Tasks.Sources
                     case SynchronizationContext sc:
                         sc.Post(s =>
                         {
-                            var tuple = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            var tuple = (Tuple<Action<object?>, object?>)s!;
                             tuple.Item1(tuple.Item2);
                         }, Tuple.Create(continuation, state));
                         break;
@@ -254,7 +255,7 @@ namespace System.Threading.Tasks.Sources
                 case SynchronizationContext sc:
                     sc.Post(s =>
                     {
-                        var state = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        var state = (Tuple<Action<object?>, object?>)s!;
                         state.Item1(state.Item2);
                     }, Tuple.Create(_continuation, _continuationState));
                     break;
index a4a6592..4fb8d9a 100644 (file)
@@ -207,12 +207,14 @@ namespace System.Threading.Tasks
         {
             Debug.Assert(task != null, "Null Task objects can't be added to the ActiveTasks collection");
 
+#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
             LazyInitializer.EnsureInitialized(ref s_currentActiveTasks, () => new Dictionary<int, Task>());
+#pragma warning restore CS8634
 
             int taskId = task.Id;
-            lock (s_currentActiveTasks!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            lock (s_currentActiveTasks!) // TODO-NULLABLE: Remove ! when nullable attributes are respected
             {
-                s_currentActiveTasks![taskId] = task; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                s_currentActiveTasks[taskId] = task;
             }
             //always return true to keep signature as bool for backwards compatibility
             return true;
@@ -427,7 +429,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ArgumentNullException">
         /// The <paramref name="action"/> argument is null.
         /// </exception>
-        public Task(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Action<object?> action, object? state)
             : this(action, state, null, default, TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
         }
@@ -444,7 +446,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
         /// has already been disposed.
         /// </exception>
-        public Task(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Action<object?> action, object? state, CancellationToken cancellationToken)
             : this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
         {
         }
@@ -465,7 +467,7 @@ namespace System.Threading.Tasks
         /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
         /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
         /// </exception>
-        public Task(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Action<object?> action, object? state, TaskCreationOptions creationOptions)
             : this(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null)
         {
         }
@@ -490,7 +492,7 @@ namespace System.Threading.Tasks
         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
         /// has already been disposed.
         /// </exception>
-        public Task(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
             : this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
         {
         }
@@ -634,7 +636,7 @@ namespace System.Threading.Tasks
                         if (antecedent == null)
                         {
                             // if no antecedent was specified, use this task's reference as the cancellation state object
-                            ctr = cancellationToken.UnsafeRegister(t => ((Task)t!).InternalCancel(false), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            ctr = cancellationToken.UnsafeRegister(t => ((Task)t!).InternalCancel(false), this);
                         }
                         else
                         {
@@ -1050,7 +1052,7 @@ namespace System.Threading.Tasks
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
             }
 
-            InternalRunSynchronously(scheduler!, waitForCompletion: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            InternalRunSynchronously(scheduler!, waitForCompletion: true); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
         }
 
         //
@@ -1356,7 +1358,9 @@ namespace System.Threading.Tasks
         /// <returns>The initialized contingent properties object.</returns>
         internal ContingentProperties EnsureContingentPropertiesInitialized()
         {
-            return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties())!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+#pragma warning disable CS8634 // TODO-NULLABLE: Remove warning disable when nullable attributes are respected
+            return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties())!;
+#pragma warning restore CS8634
         }
 
         /// <summary>
@@ -1525,7 +1529,7 @@ namespace System.Threading.Tasks
                     }
                 }
 
-                return contingentProps.m_completionEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return contingentProps.m_completionEvent!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -1815,7 +1819,7 @@ namespace System.Threading.Tasks
 
             lock (props)
             {
-                props.m_exceptionsHolder!.Add(exceptionObject, representsCancellation); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                props.m_exceptionsHolder!.Add(exceptionObject, representsCancellation); // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -3613,13 +3617,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromTask(
-                this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationAction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationTask;
         }
@@ -3803,13 +3807,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task continuationTask = new ContinuationTaskFromTask(
-                this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationAction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationTask;
         }
@@ -4006,13 +4010,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
-                this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationFunction!, null, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationTask;
         }
@@ -4213,13 +4217,13 @@ namespace System.Threading.Tasks
             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
             Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
-                this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                this, continuationFunction!, state, // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 creationOptions, internalOptions
             );
 
             // Register the continuation.  If synchronous execution is requested, this may
             // actually invoke the continuation before returning.
-            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             return continuationTask;
         }
@@ -4724,7 +4728,7 @@ namespace System.Threading.Tasks
             bool returnValue = true;
 
             // Collects incomplete tasks in "waitedOnTaskList"
-            for (int i = tasks!.Length - 1; i >= 0; i--) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int i = tasks!.Length - 1; i >= 0; i--) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 Task task = tasks[i];
 
@@ -4733,7 +4737,7 @@ namespace System.Threading.Tasks
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
                 }
 
-                bool taskIsCompleted = task!.IsCompleted; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                bool taskIsCompleted = task!.IsCompleted; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 if (!taskIsCompleted)
                 {
                     // try inlining the task only if we have an infinite timeout and an empty cancellation token
@@ -5089,7 +5093,7 @@ namespace System.Threading.Tasks
             // Make a pass through the loop to check for any tasks that may have
             // already been completed, and to verify that no tasks are null.
 
-            for (int taskIndex = 0; taskIndex < tasks!.Length; taskIndex++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            for (int taskIndex = 0; taskIndex < tasks!.Length; taskIndex++) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 Task task = tasks[taskIndex];
 
@@ -5098,7 +5102,7 @@ namespace System.Threading.Tasks
                     ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
                 }
 
-                if (signaledTaskIndex == -1 && task!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                if (signaledTaskIndex == -1 && task!.IsCompleted) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 {
                     // We found our first completed task.  Store it, but we can't just return here,
                     // as we still need to validate the whole array for nulls.
@@ -5150,7 +5154,7 @@ namespace System.Threading.Tasks
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
             var task = new Task();
-            bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             Debug.Assert(succeeded, "This should always succeed on a new task.");
             return task;
         }
@@ -5164,7 +5168,7 @@ namespace System.Threading.Tasks
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
             var task = new Task<TResult>();
-            bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             Debug.Assert(succeeded, "This should always succeed on a new task.");
             return task;
         }
@@ -5187,7 +5191,7 @@ namespace System.Threading.Tasks
         {
             if (!cancellationToken.IsCancellationRequested)
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.cancellationToken);
-            return new Task<TResult>(true, default!, TaskCreationOptions.None, cancellationToken); // TODO-NULLABLE-GENERIC
+            return new Task<TResult>(true, default!, TaskCreationOptions.None, cancellationToken); // TODO-NULLABLE: Remove ! when nullable attributes are respected
         }
 
         /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified exception.</summary>
@@ -5324,7 +5328,7 @@ namespace System.Threading.Tasks
                 return Task.FromCanceled(cancellationToken);
 
             // Kick off initial Task, which will call the user-supplied function and yield a Task.
-            Task<Task?> task1 = Task<Task?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Task<Task?> task1 = Task<Task?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             // Create a promise-style Task to be used as a proxy for the operation
             // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
@@ -5369,7 +5373,7 @@ namespace System.Threading.Tasks
                 return Task.FromCanceled<TResult>(cancellationToken);
 
             // Kick off initial Task, which will call the user-supplied function and yield a Task.
-            Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
 
             // Create a promise-style Task to be used as a proxy for the operation
             // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
@@ -5492,7 +5496,7 @@ namespace System.Threading.Tasks
 
                 if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout
                 {
-                    _timer = new TimerQueueTimer(state => ((DelayPromise)state!).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    _timer = new TimerQueueTimer(state => ((DelayPromise)state!).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false);
                     if (IsCanceled)
                     {
                         // Handle rare race condition where cancellation occurs prior to our having created and stored the timer, in which case
@@ -5531,7 +5535,7 @@ namespace System.Threading.Tasks
                 Debug.Assert(token.CanBeCanceled);
 
                 _token = token;
-                _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state!).CompleteCanceled(), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state!).CompleteCanceled(), this);
             }
 
             private void CompleteCanceled()
@@ -5596,7 +5600,7 @@ namespace System.Threading.Tasks
                 foreach (var task in tasks)
                 {
                     if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                    taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    taskArray[index++] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 }
                 return InternalWhenAll(taskArray);
             }
@@ -5604,10 +5608,10 @@ namespace System.Threading.Tasks
             // Do some argument checking and convert tasks to a List (and later an array).
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
             List<Task> taskList = new List<Task>();
-            foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            foreach (Task task in tasks!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                taskList.Add(task!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             // Delegate the rest to InternalWhenAll()
@@ -5646,7 +5650,7 @@ namespace System.Threading.Tasks
             // Do some argument checking and make a defensive copy of the tasks array
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
 
-            int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int taskCount = tasks!.Length; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (taskCount == 0) return InternalWhenAll(tasks); // Small optimization in the case of an empty array.
 
             Task[] tasksCopy = new Task[taskCount];
@@ -5654,7 +5658,7 @@ namespace System.Threading.Tasks
             {
                 Task task = tasks[i];
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                tasksCopy[i] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             // The rest can be delegated to InternalWhenAll()
@@ -5840,7 +5844,7 @@ namespace System.Threading.Tasks
                 foreach (var task in tasks)
                 {
                     if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                    taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                    taskArray[index++] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
                 }
                 return InternalWhenAll<TResult>(taskArray);
             }
@@ -5848,10 +5852,10 @@ namespace System.Threading.Tasks
             // Do some argument checking and convert tasks into a List (later an array)
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
             List<Task<TResult>> taskList = new List<Task<TResult>>();
-            foreach (Task<TResult> task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            foreach (Task<TResult> task in tasks!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                taskList.Add(task!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             // Delegate the rest to InternalWhenAll<TResult>().
@@ -5893,7 +5897,7 @@ namespace System.Threading.Tasks
             // Do some argument checking and make a defensive copy of the tasks array
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
 
-            int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            int taskCount = tasks!.Length; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (taskCount == 0) return InternalWhenAll<TResult>(tasks); // small optimization in the case of an empty task array
 
             Task<TResult>[] tasksCopy = new Task<TResult>[taskCount];
@@ -5901,7 +5905,7 @@ namespace System.Threading.Tasks
             {
                 Task<TResult> task = tasks[i];
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                tasksCopy[i] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             // Delegate the rest to InternalWhenAll<TResult>()
@@ -6060,7 +6064,7 @@ namespace System.Threading.Tasks
         public static Task<Task> WhenAny(params Task[] tasks)
         {
             if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
-            if (tasks!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (tasks!.Length == 0) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
             }
@@ -6073,7 +6077,7 @@ namespace System.Threading.Tasks
             {
                 Task task = tasks[i];
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                tasksCopy[i] = task!; // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             // Previously implemented CommonCWAnyLogic() can handle the rest
@@ -6102,10 +6106,10 @@ namespace System.Threading.Tasks
             // Make a defensive copy, as the user may manipulate the tasks collection
             // after we return but before the WhenAny asynchronously completes.
             List<Task> taskList = new List<Task>();
-            foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            foreach (Task task in tasks!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
-                taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                taskList.Add(task!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             if (taskList.Count == 0)
@@ -6597,7 +6601,7 @@ namespace System.Threading.Tasks
             ThreadPool.UnsafeQueueUserWorkItem(state =>
             {
                 // InvokeCore(completingTask);
-                var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!;
                 tuple.Item1.InvokeCore(tuple.Item2);
             }, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask));
         }
@@ -6673,7 +6677,7 @@ namespace System.Threading.Tasks
                     if (Task.s_asyncDebuggingEnabled)
                         RemoveFromActiveTasks(this);
 
-                    result = TrySetResult(taskTResult != null ? taskTResult.Result : default!); // TODO-NULLABLE-GENERIC
+                    result = TrySetResult(taskTResult != null ? taskTResult.Result : default!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     break;
             }
             return result;
index 8773eb4..b0c79e6 100644 (file)
@@ -150,7 +150,7 @@ namespace System.Threading.Tasks
         {
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
-            bool rval = _task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            bool rval = _task.TrySetException(exception!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             if (!rval && !_task.IsCompleted) SpinUntilCompleted();
             return rval;
         }
@@ -180,11 +180,11 @@ namespace System.Threading.Tasks
             if (exceptions == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exceptions);
 
             List<Exception> defensiveCopy = new List<Exception>();
-            foreach (Exception e in exceptions!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            foreach (Exception e in exceptions!) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 if (e == null)
                     ThrowHelper.ThrowArgumentException(ExceptionResource.TaskCompletionSourceT_TrySetException_NullException, ExceptionArgument.exceptions);
-                defensiveCopy.Add(e!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+                defensiveCopy.Add(e!); // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             }
 
             if (defensiveCopy.Count == 0)
@@ -216,7 +216,7 @@ namespace System.Threading.Tasks
         {
             if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
 
-            if (!TrySetException(exception!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+            if (!TrySetException(exception!)) // TODO-NULLABLE: Remove ! when [DoesNotReturn] respected
             {
                 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
             }
index 65547fb..fbe7733 100644 (file)
@@ -492,7 +492,7 @@ namespace System.Threading.Tasks
                 {
                     try
                     {
-                        ((Action)state!)(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                        ((Action)state!)();
                     }
                     catch (Exception exception)
                     {
index 3929a08..786e132 100644 (file)
@@ -396,7 +396,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task StartNew(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task StartNew(Action<object?> action, object? state)
         {
             Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
@@ -425,7 +425,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken)
         {
             Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask),
@@ -455,7 +455,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task StartNew(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task StartNew(Action<object?> action, object? state, TaskCreationOptions creationOptions)
         {
             Task? currTask = Task.InternalCurrent;
             return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
@@ -496,7 +496,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken,
                             TaskCreationOptions creationOptions, TaskScheduler scheduler)
         {
             return Task.InternalStartNew(
@@ -657,7 +657,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state)
         {
             Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -690,7 +690,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken)
         {
             Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
@@ -724,7 +724,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions)
         {
             Task? currTask = Task.InternalCurrent;
             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -769,7 +769,7 @@ namespace System.Threading.Tasks
         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
         /// for both simplicity and performance.
         /// </remarks>
-        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken,
             TaskCreationOptions creationOptions, TaskScheduler scheduler)
         {
             return Task<TResult>.StartNew(
index b6afade..f79a87a 100644 (file)
@@ -298,7 +298,7 @@ namespace System.Threading.Tasks
                 Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object?>(), null);
                 activeTaskSchedulers = s_activeTaskSchedulers;
             }
-            activeTaskSchedulers!.Add(this, null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            activeTaskSchedulers!.Add(this, null); // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
         }
 
         /// <summary>
index 884ae0b..75c6fd9 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks.Sources;
@@ -415,7 +416,7 @@ namespace System.Threading.Tasks
         /// <summary>null if <see cref="_result"/> has the result, otherwise a <see cref="Task{TResult}"/> or a <see cref="IValueTaskSource{TResult}"/>.</summary>
         internal readonly object? _obj;
         /// <summary>The result to be used if the operation completed successfully synchronously.</summary>
-        internal readonly TResult _result;
+        [AllowNull] internal readonly TResult _result;
         /// <summary>Opaque value passed through to the <see cref="IValueTaskSource{TResult}"/>.</summary>
         internal readonly short _token;
         /// <summary>true to continue on the captured context; otherwise, false.</summary>
@@ -449,7 +450,7 @@ namespace System.Threading.Tasks
 
             _obj = task;
 
-            _result = default!; // TODO-NULLABLE-GENERIC
+            _result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
             _continueOnCapturedContext = true;
             _token = 0;
         }
@@ -468,7 +469,7 @@ namespace System.Threading.Tasks
             _obj = source;
             _token = token;
 
-            _result = default!; // TODO-NULLABLE-GENERIC
+            _result = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
             _continueOnCapturedContext = true;
         }
 
index 39f0f63..9707b03 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.ConstrainedExecution;
 using System.Security.Principal;
@@ -151,7 +152,7 @@ namespace System.Threading
                     }
                     Interlocked.CompareExchange(ref s_asyncLocalPrincipal, new AsyncLocal<IPrincipal?>(), null);
                 }
-                s_asyncLocalPrincipal!.Value = value; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                s_asyncLocalPrincipal!.Value = value; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
@@ -282,7 +283,8 @@ namespace System.Threading
         public static int VolatileRead(ref int address) => Volatile.Read(ref address);
         public static long VolatileRead(ref long address) => Volatile.Read(ref address);
         public static IntPtr VolatileRead(ref IntPtr address) => Volatile.Read(ref address);
-        public static object? VolatileRead(ref object? address) => Volatile.Read(ref address); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        [return: NotNullIfNotNull("address")]
+        public static object? VolatileRead(ref object? address) => Volatile.Read(ref address);
         [CLSCompliant(false)]
         public static sbyte VolatileRead(ref sbyte address) => Volatile.Read(ref address);
         public static float VolatileRead(ref float address) => Volatile.Read(ref address);
@@ -300,7 +302,7 @@ namespace System.Threading
         public static void VolatileWrite(ref int address, int value) => Volatile.Write(ref address, value);
         public static void VolatileWrite(ref long address, long value) => Volatile.Write(ref address, value);
         public static void VolatileWrite(ref IntPtr address, IntPtr value) => Volatile.Write(ref address, value);
-        public static void VolatileWrite(ref object? address, object? value) => Volatile.Write(ref address, value);
+        public static void VolatileWrite([NotNullIfNotNull("value")] ref object? address, object? value) => Volatile.Write(ref address, value);
         [CLSCompliant(false)]
         public static void VolatileWrite(ref sbyte address, sbyte value) => Volatile.Write(ref address, value);
         public static void VolatileWrite(ref float address, float value) => Volatile.Write(ref address, value);
index f57afb9..1126ea3 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 // A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing 
 // thread; this provides an alternative to using a ThreadStatic static variable and having 
@@ -201,7 +202,7 @@ namespace System.Threading
 
                     // And clear the references from the slot table to the linked slot and the value so that
                     // both can get garbage collected.
-                    slotArray[id].Value!._value = default!; // TODO-NULLABLE-GENERIC
+                    slotArray[id].Value!._value = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                     slotArray[id].Value = null;
                 }
             }
@@ -248,6 +249,7 @@ namespace System.Threading
         /// <typeparamref name="T"/> will be used.
         /// </remarks>
         [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+        [MaybeNull]
         public T Value
         {
             get
@@ -304,6 +306,7 @@ namespace System.Threading
             }
         }
 
+        [return: MaybeNull]
         private T GetValueSlow()
         {
             // If the object has been disposed, the id will be -1.
@@ -319,7 +322,7 @@ namespace System.Threading
             T value;
             if (_valueFactory == null)
             {
-                value = default!; // TODO-NULLABLE-GENERIC
+                value = default!;
             }
             else
             {
@@ -466,7 +469,7 @@ namespace System.Threading
             {
                 // We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
                 // objects will never be assigned to another ThreadLocal instance.
-                valueList.Add(linkedSlot._value);
+                valueList.Add(linkedSlot._value!);
             }
 
             return valueList;
@@ -493,7 +496,7 @@ namespace System.Threading
                 {
                     // We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
                     // objects will never be assigned to another ThreadLocal instance.
-                    yield return linkedSlot._value;
+                    yield return linkedSlot._value!;
                 }
             }
         }
@@ -536,6 +539,7 @@ namespace System.Threading
 
         /// <summary>Gets the value of the ThreadLocal&lt;T&gt; for debugging display purposes. It takes care of getting
         /// the value for the current thread in the ThreadLocal mode.</summary>
+        [MaybeNull]
         internal T ValueForDebugDisplay
         {
             get
@@ -545,7 +549,7 @@ namespace System.Threading
 
                 LinkedSlot? slot;
                 if (slotArray == null || id >= slotArray.Length || (slot = slotArray[id].Value) == null || !_initialized)
-                    return default!; // TODO-NULLABLE-GENERIC
+                    return default!;
                 return slot._value;
             }
         }
@@ -671,7 +675,7 @@ namespace System.Threading
             internal volatile LinkedSlotVolatile[]? _slotArray;
 
             // The value for this slot.
-            internal T _value = default!; // TODO-NULLABLE-GENERIC
+            [AllowNull, MaybeNull] internal T _value = default!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
         }
 
         /// <summary>
index 8789065..be94ccb 100644 (file)
@@ -612,7 +612,7 @@ namespace System.Threading
 
             if (toSignal is WaitHandle wh)
             {
-                EventWaitHandle.Set(wh.SafeWaitHandle!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+                EventWaitHandle.Set(wh.SafeWaitHandle);
             }
             else
             {
index 26d33a4..5c1df63 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.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.Versioning;
 using Internal.Runtime.CompilerServices;
@@ -218,12 +219,13 @@ namespace System.Threading
 
         [Intrinsic]
         [NonVersionable]
+        [return: NotNullIfNotNull("location")]
         public static T Read<T>(ref T location) where T : class? =>
             Unsafe.As<T>(Unsafe.As<T, VolatileObject>(ref location).Value);
 
         [Intrinsic]
         [NonVersionable]
-        public static void Write<T>(ref T location, T value) where T : class? =>
+        public static void Write<T>([NotNullIfNotNull("value")] ref T location, T value) where T : class? =>
             Unsafe.As<T, VolatileObject>(ref location).Value = value;
         #endregion
     }
index 20aa3f7..75965a3 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using Microsoft.Win32.SafeHandles;
 
 namespace System.Threading
@@ -78,7 +79,8 @@ namespace System.Threading
             }
         }
 
-        public SafeWaitHandle? SafeWaitHandle // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
+        [AllowNull]
+        public SafeWaitHandle SafeWaitHandle
         {
             get
             {
@@ -334,7 +336,7 @@ namespace System.Threading
                 {
                     if (safeWaitHandles[i] != null)
                     {
-                        safeWaitHandles[i]!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        safeWaitHandles[i]!.DangerousRelease(); // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
                         safeWaitHandles[i] = null;
                     }
                 }
index f6805d8..e79b785 100644 (file)
@@ -38,6 +38,7 @@
 using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 
@@ -46,83 +47,98 @@ namespace System
     [StackTraceHidden]
     internal static class ThrowHelper
     {
+        [DoesNotReturn]
         internal static void ThrowArrayTypeMismatchException()
         {
             throw new ArrayTypeMismatchException();
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidTypeWithPointersNotSupported(Type targetType)
         {
             throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, targetType));
         }
 
+        [DoesNotReturn]
         internal static void ThrowIndexOutOfRangeException()
         {
             throw new IndexOutOfRangeException();
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException()
         {
             throw new ArgumentOutOfRangeException();
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentException_DestinationTooShort()
         {
             throw new ArgumentException(SR.Argument_DestinationTooShort, "destination");
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentException_OverlapAlignmentMismatch()
         {
             throw new ArgumentException(SR.Argument_OverlapAlignmentMismatch);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentException_CannotExtractScalar(ExceptionArgument argument)
         {
             throw GetArgumentException(ExceptionResource.Argument_CannotExtractScalar, argument);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRange_IndexException()
         {
             throw GetArgumentOutOfRangeException(ExceptionArgument.index,
                                                     ExceptionResource.ArgumentOutOfRange_Index);
         }
 
+        [DoesNotReturn]
         internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException()
         {
             throw GetArgumentOutOfRangeException(ExceptionArgument.index,
                                                     ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
         }
 
+        [DoesNotReturn]
         internal static void ThrowValueArgumentOutOfRange_NeedNonNegNumException()
         {
             throw GetArgumentOutOfRangeException(ExceptionArgument.value,
                                                     ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
         }
 
+        [DoesNotReturn]
         internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum()
         {
             throw GetArgumentOutOfRangeException(ExceptionArgument.length,
                                                     ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
         }
 
+        [DoesNotReturn]
         internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index()
         {
             throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex,
                                                     ExceptionResource.ArgumentOutOfRange_Index);
         }
 
+        [DoesNotReturn]
         internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count()
         {
             throw GetArgumentOutOfRangeException(ExceptionArgument.count,
                                                     ExceptionResource.ArgumentOutOfRange_Count);
         }
 
+        [DoesNotReturn]
         internal static void ThrowWrongKeyTypeArgumentException<T>(T key, Type targetType)
         {
             // Generic key to move the boxing to the right hand side of throw
             throw GetWrongKeyTypeArgumentException((object?)key, targetType);
         }
 
+        [DoesNotReturn]
         internal static void ThrowWrongValueTypeArgumentException<T>(T value, Type targetType)
         {
             // Generic key to move the boxing to the right hand side of throw
@@ -134,23 +150,27 @@ namespace System
             return new ArgumentException(SR.Format(SR.Argument_AddingDuplicateWithKey, key));
         }
 
+        [DoesNotReturn]
         internal static void ThrowAddingDuplicateWithKeyArgumentException<T>(T key)
         {
             // Generic key to move the boxing to the right hand side of throw
             throw GetAddingDuplicateWithKeyArgumentException((object?)key);
         }
 
+        [DoesNotReturn]
         internal static void ThrowKeyNotFoundException<T>(T key)
         {
             // Generic key to move the boxing to the right hand side of throw
             throw GetKeyNotFoundException((object?)key);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentException(ExceptionResource resource)
         {
             throw GetArgumentException(resource);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument)
         {
             throw GetArgumentException(resource, argument);
@@ -161,171 +181,205 @@ namespace System
             return new ArgumentNullException(GetArgumentName(argument));
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentNullException(ExceptionArgument argument)
         {
             throw GetArgumentNullException(argument);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentNullException(ExceptionResource resource)
         {
             throw new ArgumentNullException(GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentNullException(ExceptionArgument argument, ExceptionResource resource)
         {
             throw new ArgumentNullException(GetArgumentName(argument), GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument)
         {
             throw new ArgumentOutOfRangeException(GetArgumentName(argument));
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
         {
             throw GetArgumentOutOfRangeException(argument, resource);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource)
         {
             throw GetArgumentOutOfRangeException(argument, paramNumber, resource);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException()
         {
             throw new InvalidOperationException();
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException(ExceptionResource resource)
         {
             throw GetInvalidOperationException(resource);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_OutstandingReferences()
         {
             throw new InvalidOperationException(SR.Memory_OutstandingReferences);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e)
         {
             throw new InvalidOperationException(GetResourceString(resource), e);
         }
 
+        [DoesNotReturn]
         internal static void ThrowSerializationException(ExceptionResource resource)
         {
             throw new SerializationException(GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowSecurityException(ExceptionResource resource)
         {
             throw new System.Security.SecurityException(GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowRankException(ExceptionResource resource)
         {
             throw new RankException(GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowNotSupportedException(ExceptionResource resource)
         {
             throw new NotSupportedException(GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowUnauthorizedAccessException(ExceptionResource resource)
         {
             throw new UnauthorizedAccessException(GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource)
         {
             throw new ObjectDisposedException(objectName, GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowObjectDisposedException(ExceptionResource resource)
         {
             throw new ObjectDisposedException(null, GetResourceString(resource));
         }
 
+        [DoesNotReturn]
         internal static void ThrowNotSupportedException()
         {
             throw new NotSupportedException();
         }
 
+        [DoesNotReturn]
         internal static void ThrowAggregateException(List<Exception> exceptions)
         {
             throw new AggregateException(exceptions);
         }
 
+        [DoesNotReturn]
         internal static void ThrowOutOfMemoryException()
         {
             throw new OutOfMemoryException();
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentException_Argument_InvalidArrayType()
         {
             throw new ArgumentException(SR.Argument_InvalidArrayType);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_InvalidOperation_EnumNotStarted()
         {
             throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_InvalidOperation_EnumEnded()
         {
             throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_EnumCurrent(int index)
         {
             throw GetInvalidOperationException_EnumCurrent(index);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
         {
             throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
         {
             throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_InvalidOperation_NoValue()
         {
             throw new InvalidOperationException(SR.InvalidOperation_NoValue);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
         {
             throw new InvalidOperationException(SR.InvalidOperation_ConcurrentOperationsNotSupported);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_HandleIsNotInitialized()
         {
             throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotInitialized);
         }
 
+        [DoesNotReturn]
         internal static void ThrowInvalidOperationException_HandleIsNotPinned()
         {
             throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotPinned);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array? array, int offset, int count)
         {
             throw GetArraySegmentCtorValidationFailedException(array, offset, count);
         }
 
+        [DoesNotReturn]
         internal static void ThrowFormatException_BadFormatSpecifier()
         {
             throw new FormatException(SR.Argument_BadFormatSpecifier);
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
         {
             throw new ArgumentOutOfRangeException("precision", SR.Format(SR.Argument_PrecisionTooLarge, StandardFormat.MaxPrecision));
         }
 
+        [DoesNotReturn]
         internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit()
         {
             throw new ArgumentOutOfRangeException("symbol", SR.Argument_BadFormatSpecifier);
@@ -399,7 +453,7 @@ namespace System
         internal static void IfNullAndNullsAreIllegalThenThrow<T>(object? value, ExceptionArgument argName)
         {
             // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
-            if (!(default(T)! == null) && value == null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
+            if (!(default(T)! == null) && value == null) // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
                 ThrowHelper.ThrowArgumentNullException(argName);
         }
 
index b9dc233..0775e5b 100644 (file)
@@ -42,7 +42,7 @@ namespace System
                     object o = new object();
                     Interlocked.CompareExchange<object?>(ref s_InternalSyncObject, o, null);
                 }
-                return s_InternalSyncObject!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return s_InternalSyncObject!; // TODO-NULLABLE: Remove ! when compiler specially-recognizes CompareExchange for nullability
             }
         }
 
index 4ba7f28..a3ffb1c 100644 (file)
@@ -9,7 +9,7 @@ namespace System
     public sealed partial class TimeZoneInfo
     {
         [Serializable]
-        public sealed class AdjustmentRule : IEquatable<AdjustmentRule?>, ISerializable, IDeserializationCallback
+        public sealed class AdjustmentRule : IEquatable<AdjustmentRule>, ISerializable, IDeserializationCallback
         {
             private static readonly TimeSpan DaylightDeltaAdjustment = TimeSpan.FromHours(24.0);
             private static readonly TimeSpan MaxDaylightDelta = TimeSpan.FromHours(12.0);
@@ -44,7 +44,9 @@ namespace System
                 (DaylightTransitionStart != default && DaylightTransitionStart.TimeOfDay != DateTime.MinValue) ||
                 (DaylightTransitionEnd != default && DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1));
 
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
             public bool Equals(AdjustmentRule? other) =>
+#pragma warning restore CS8614
                 other != null &&
                 _dateStart == other._dateStart &&
                 _dateEnd == other._dateEnd &&
index bc6ac41..1187eb5 100644 (file)
@@ -5,11 +5,13 @@
 using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.IO;
 using System.Text;
 using System.Threading;
 using System.Security;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
 using Internal.IO;
@@ -307,7 +309,7 @@ namespace System
         /// 3. Look for the data in GetTimeZoneDirectory()/localtime.
         /// 4. Use UTC if all else fails.
         /// </summary>
-        private static bool TryGetLocalTzFile(out byte[]? rawData, out string? id) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        private static bool TryGetLocalTzFile([NotNullWhen(true)] out byte[]? rawData, [NotNullWhen(true)] out string? id)
         {
             rawData = null;
             id = null;
@@ -357,7 +359,7 @@ namespace System
             return result;
         }
 
-        private static bool TryLoadTzFile(string tzFilePath, ref byte[]? rawData, ref string? id) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        private static bool TryLoadTzFile(string tzFilePath, [NotNullWhen(true)] ref byte[]? rawData, [NotNullWhen(true)] ref string? id)
         {
             if (File.Exists(tzFilePath))
             {
@@ -394,7 +396,7 @@ namespace System
             if (symlinkPath != null)
             {
                 // symlinkPath can be relative path, use Path to get the full absolute path.
-                symlinkPath = Path.GetFullPath(symlinkPath, Path.GetDirectoryName(tzFilePath)!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                symlinkPath = Path.GetFullPath(symlinkPath, Path.GetDirectoryName(tzFilePath)!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
                 string timeZoneDirectory = GetTimeZoneDirectory();
                 if (symlinkPath.StartsWith(timeZoneDirectory, StringComparison.Ordinal))
@@ -614,9 +616,9 @@ namespace System
         {
             byte[]? rawData;
             string? id;
-            if (TryGetLocalTzFile(out rawData, out id)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+            if (TryGetLocalTzFile(out rawData, out id))
             {
-                TimeZoneInfo? result = GetTimeZoneFromTzData(rawData!, id!);
+                TimeZoneInfo? result = GetTimeZoneFromTzData(rawData!, id!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 if (result != null)
                 {
                     return result;
@@ -991,7 +993,7 @@ namespace System
                     {
                         if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
                         {
-                            NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                            NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
                         }
 
                         rulesList.Add(r);
index a261b75..e1cfe4e 100644 (file)
@@ -260,7 +260,7 @@ namespace System
                 if (TryGetTimeZone(dynamicTimeZoneKeyName, dynamicTimeZoneInformation.DynamicDaylightTimeDisabled != 0, out TimeZoneInfo? zone, out _, cachedData) == TimeZoneInfoResult.Success)
                 {
                     // successfully loaded the time zone from the registry
-                    return zone!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    return zone!;
                 }
             }
 
@@ -274,7 +274,7 @@ namespace System
                 if (TryGetTimeZone(id, dstDisabled, out TimeZoneInfo? zone, out _, cachedData) == TimeZoneInfoResult.Success)
                 {
                     // successfully loaded the time zone from the registry
-                    return zone!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    return zone!;
                 }
             }
 
@@ -352,7 +352,7 @@ namespace System
 
             if (result == TimeZoneInfoResult.Success)
             {
-                return value!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                return value!;
             }
             else if (result == TimeZoneInfoResult.InvalidTimeZoneException)
             {
@@ -563,8 +563,8 @@ namespace System
                     // read LastEntry   {(yearN, 1, 1) - MaxValue       }
 
                     // read the FirstEntry and LastEntry key values (ex: "1980", "2038")
-                    int first = (int)dynamicKey.GetValue(FirstEntryValue, -1)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
-                    int last = (int)dynamicKey.GetValue(LastEntryValue, -1)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
+                    int first = (int)dynamicKey.GetValue(FirstEntryValue, -1)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
+                    int last = (int)dynamicKey.GetValue(LastEntryValue, -1)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
 
                     if (first == -1 || last == -1 || first > last)
                     {
index cef843f..768385c 100644 (file)
@@ -5,6 +5,7 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Runtime.Serialization;
 using System.Threading;
@@ -29,7 +30,7 @@ namespace System
 
     [Serializable]
     [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-    public sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo?>, ISerializable, IDeserializationCallback
+    public sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
     {
         private enum TimeZoneInfoResult
         {
@@ -764,7 +765,9 @@ namespace System
         /// Returns value equality. Equals does not compare any localizable
         /// String objects (DisplayName, StandardName, DaylightName).
         /// </summary>
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
         public bool Equals(TimeZoneInfo? other) =>
+#pragma warning restore CS8614
             other != null &&
             string.Equals(_id, other._id, StringComparison.OrdinalIgnoreCase) &&
             HasSameRules(other);
@@ -1902,17 +1905,17 @@ namespace System
                 // uses reference equality with the Utc object.
                 if (!id.Equals(UtcId,  StringComparison.OrdinalIgnoreCase))
                 {
-                    cachedData._systemTimeZones.Add(id, match!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    cachedData._systemTimeZones.Add(id, match!);
                 }
 
-                if (dstDisabled && match!._supportsDaylightSavingTime) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                if (dstDisabled && match!._supportsDaylightSavingTime)
                 {
                     // we found a cache hit but we want a time zone without DST and this one has DST data
                     value = CreateCustomTimeZone(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName);
                 }
                 else
                 {
-                    value = new TimeZoneInfo(match!._id, match._baseUtcOffset, match._displayName, match._standardDisplayName, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    value = new TimeZoneInfo(match!._id, match._baseUtcOffset, match._displayName, match._standardDisplayName,
                                           match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false);
                 }
             }
@@ -2017,7 +2020,7 @@ namespace System
         /// This method should not be called at all but is here in case something changes in the future
         /// or if really old time zones are present on the OS (no combination is known at the moment)
         /// </summary>
-        private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, ref AdjustmentRule adjustmentRule)
+        private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, [NotNull] ref AdjustmentRule adjustmentRule)
         {
             // Certain time zones such as:
             //       Time Zone  start date  end date    offset
index 6439720..034264d 100644 (file)
@@ -156,7 +156,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return comparer.GetHashCode(m_Item1!); // TODO-NULLABLE-GENERIC
+            return comparer.GetHashCode(m_Item1!);
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -261,7 +261,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!)); // TODO-NULLABLE-GENERIC
+            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!));
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -379,7 +379,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!)); // TODO-NULLABLE-GENERIC
+            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!));
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -508,7 +508,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!)); // TODO-NULLABLE-GENERIC
+            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!));
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -648,7 +648,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!)); // TODO-NULLABLE-GENERIC
+            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!));
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -799,7 +799,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!)); // TODO-NULLABLE-GENERIC
+            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!));
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -961,7 +961,7 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!)); // TODO-NULLABLE-GENERIC
+            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!));
         }
 
         int ITupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -1031,7 +1031,7 @@ namespace System
 
     [Serializable]
     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-    public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple
+    public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple where TRest : object
     {
         private readonly T1 m_Item1; // Do not rename (binary serialization)
         private readonly T2 m_Item2; // Do not rename (binary serialization)
@@ -1140,7 +1140,7 @@ namespace System
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
             // We want to have a limited hash in this case.  We'll use the last 8 elements of the tuple
-            ITupleInternal t = (ITupleInternal)m_Rest!; // TODO-NULLABLE-GENERIC
+            ITupleInternal t = (ITupleInternal)m_Rest;
             if (t.Length >= 8) { return t.GetHashCode(comparer); }
 
             // In this case, the rest memeber has less than 8 elements so we need to combine some our elements with the elements in rest
@@ -1148,19 +1148,19 @@ namespace System
             switch (k)
             {
                 case 1:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
                 case 2:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
                 case 3:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
                 case 4:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
                 case 5:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
                 case 6:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
                 case 7:
-                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer));
             }
             Debug.Fail("Missed all cases for computing Tuple hash code");
             return -1;
@@ -1193,7 +1193,7 @@ namespace System
             sb.Append(", ");
             sb.Append(m_Item7);
             sb.Append(", ");
-            return ((ITupleInternal)m_Rest!).ToString(sb); // TODO-NULLABLE-GENERIC
+            return ((ITupleInternal)m_Rest).ToString(sb);
         }
 
         /// <summary>
@@ -1203,7 +1203,7 @@ namespace System
         {
             get
             {
-                return 7 + ((ITupleInternal)Rest!).Length; // TODO-NULLABLE-GENERIC
+                return 7 + ((ITupleInternal)Rest).Length;
             }
         }
 
@@ -1232,7 +1232,7 @@ namespace System
                         return Item7;
                 }
 
-                return ((ITupleInternal)Rest!)[index - 7]; // TODO-NULLABLE-GENERIC
+                return ((ITupleInternal)Rest)[index - 7];
             }
         }
     }
index 0e871c6..0f171ec 100644 (file)
@@ -135,7 +135,7 @@ namespace System
             for (int i = 0; i < c.Length; i++)
             {
                 if (c[i] != null)
-                    ret[cnt++] = c[i]!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                    ret[cnt++] = c[i]!; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
             return ret;
         }
@@ -270,7 +270,7 @@ namespace System
             {
                 for (i = 0; i < m.Length; i++)
                     if (m[i] != null)
-                        ret[cnt++] = m[i]!;  // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        ret[cnt++] = m[i]!;  // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             // Copy the Constructors
@@ -278,7 +278,7 @@ namespace System
             {
                 for (i = 0; i < c.Length; i++)
                     if (c[i] != null)
-                        ret[cnt++] = c[i]!;  // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        ret[cnt++] = c[i]!;  // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             // Copy the Fields
@@ -286,7 +286,7 @@ namespace System
             {
                 for (i = 0; i < f.Length; i++)
                     if (f[i] != null)
-                        ret[cnt++] = f[i]!;  // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        ret[cnt++] = f[i]!;  // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             // Copy the Properties
@@ -294,7 +294,7 @@ namespace System
             {
                 for (i = 0; i < p.Length; i++)
                     if (p[i] != null)
-                        ret[cnt++] = p[i]!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        ret[cnt++] = p[i]!; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             // Copy the Events
@@ -302,7 +302,7 @@ namespace System
             {
                 for (i = 0; i < e.Length; i++)
                     if (e[i] != null)
-                        ret[cnt++] = e[i]!;  // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        ret[cnt++] = e[i]!;  // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             // Copy the Types
@@ -310,7 +310,7 @@ namespace System
             {
                 for (i = 0; i < t.Length; i++)
                     if (t[i] != null)
-                        ret[cnt++] = t[i]!;  // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644
+                        ret[cnt++] = t[i]!;  // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
             }
 
             return ret;
index 72c13b5..774f3e3 100644 (file)
@@ -411,12 +411,12 @@ namespace System
 
         int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
         {
-            return comparer.GetHashCode(Item1!); // TODO-NULLABLE-GENERIC
+            return comparer.GetHashCode(Item1!);
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
         {
-            return comparer.GetHashCode(Item1!); // TODO-NULLABLE-GENERIC
+            return comparer.GetHashCode(Item1!);
         }
 
         /// <summary>
@@ -616,7 +616,7 @@ namespace System
         private int GetHashCodeCore(IEqualityComparer comparer)
         {
             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!),
-                                               comparer.GetHashCode(Item2!)); // TODO-NULLABLE-GENERIC
+                                               comparer.GetHashCode(Item2!));
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -824,7 +824,7 @@ namespace System
         {
             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!),
                                                comparer.GetHashCode(Item2!),
-                                               comparer.GetHashCode(Item3!)); // TODO-NULLABLE-GENERIC
+                                               comparer.GetHashCode(Item3!));
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -1049,7 +1049,7 @@ namespace System
             return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!),
                                                comparer.GetHashCode(Item2!),
                                                comparer.GetHashCode(Item3!),
-                                               comparer.GetHashCode(Item4!)); // TODO-NULLABLE-GENERIC
+                                               comparer.GetHashCode(Item4!));
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -1293,7 +1293,7 @@ namespace System
                                                comparer.GetHashCode(Item2!),
                                                comparer.GetHashCode(Item3!),
                                                comparer.GetHashCode(Item4!),
-                                               comparer.GetHashCode(Item5!)); // TODO-NULLABLE-GENERIC
+                                               comparer.GetHashCode(Item5!));
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -1556,7 +1556,7 @@ namespace System
                                                comparer.GetHashCode(Item3!),
                                                comparer.GetHashCode(Item4!),
                                                comparer.GetHashCode(Item5!),
-                                               comparer.GetHashCode(Item6!)); // TODO-NULLABLE-GENERIC
+                                               comparer.GetHashCode(Item6!));
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -1838,7 +1838,7 @@ namespace System
                                                comparer.GetHashCode(Item4!),
                                                comparer.GetHashCode(Item5!),
                                                comparer.GetHashCode(Item6!),
-                                               comparer.GetHashCode(Item7!)); // TODO-NULLABLE-GENERIC
+                                               comparer.GetHashCode(Item7!));
         }
 
         int IValueTupleInternal.GetHashCode(IEqualityComparer comparer)
@@ -2203,7 +2203,7 @@ namespace System
             {
                 return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!),
                                                    comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!),
-                                                   comparer.GetHashCode(Item7!)); // TODO-NULLABLE-GENERIC
+                                                   comparer.GetHashCode(Item7!));
             }
 
             int size = rest.Length;
@@ -2214,27 +2214,27 @@ namespace System
             switch (k)
             {
                 case 1:
-                    return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7!), rest.GetHashCode(comparer));
                 case 2:
-                    return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                    return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), rest.GetHashCode(comparer));
                 case 3:
                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!),
-                                                       rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                                                       rest.GetHashCode(comparer));
                 case 4:
                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!),
-                                                       comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                                                       comparer.GetHashCode(Item7!), rest.GetHashCode(comparer));
                 case 5:
                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item3!), comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!),
-                                                       comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                                                       comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), rest.GetHashCode(comparer));
                 case 6:
                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!), comparer.GetHashCode(Item4!),
                                                        comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!),
-                                                       rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                                                       rest.GetHashCode(comparer));
                 case 7:
                 case 8:
                     return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!),
                                                        comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!),
-                                                       comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC
+                                                       comparer.GetHashCode(Item7!), rest.GetHashCode(comparer));
             }
 
             Debug.Fail("Missed all cases for computing ValueTuple hash code");
index 3b8d1cb..b3e770c 100644 (file)
@@ -6,6 +6,7 @@ using System.Globalization;
 using System.Diagnostics;
 using System.Text;
 using System.Runtime.CompilerServices;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System
 {
@@ -17,7 +18,7 @@ namespace System
 
     [Serializable]
     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-    public sealed class Version : ICloneable, IComparable, IComparable<Version?>, IEquatable<Version?>, ISpanFormattable
+    public sealed class Version : ICloneable, IComparable, IComparable<Version?>, IEquatable<Version>, ISpanFormattable
     {
         // AssemblyName depends on the order staying the same
         private readonly int _Major; // Do not rename (binary serialization)
@@ -167,7 +168,9 @@ namespace System
             return Equals(obj as Version);
         }
 
+#pragma warning disable CS8614 // TODO-NULLABLE: Covariant interface arguments (https://github.com/dotnet/roslyn/issues/35817)
         public bool Equals(Version? obj)
+#pragma warning restore CS8614
         {
             return object.ReferenceEquals(obj, this) ||
                 (!(obj is null) &&
@@ -306,7 +309,7 @@ namespace System
         public static Version Parse(ReadOnlySpan<char> input) =>
             ParseVersion(input, throwOnFailure: true)!;
 
-        public static bool TryParse(string? input, out Version? result) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+        public static bool TryParse(string? input, [NotNullWhen(true)] out Version? result)
         {
             if (input == null)
             {
@@ -317,7 +320,7 @@ namespace System
             return (result = ParseVersion(input.AsSpan(), throwOnFailure: false)) != null;
         }
 
-        public static bool TryParse(ReadOnlySpan<char> input, out Version? result) =>
+        public static bool TryParse(ReadOnlySpan<char> input, [NotNullWhen(true)] out Version? result) =>
             (result = ParseVersion(input, throwOnFailure: false)) != null;
 
         private static Version? ParseVersion(ReadOnlySpan<char> input, bool throwOnFailure)
index a833f55..b0986da 100644 (file)
@@ -130,7 +130,7 @@ namespace System
                 case SpecialFolder.System:
                     return SystemDirectory;
                 case SpecialFolder.Windows:
-                    return Path.GetDirectoryName(SystemDirectory)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
+                    return Path.GetDirectoryName(SystemDirectory)!; // TODO-NULLABLE: Remove ! when nullable attributes are respected
                 default:
                     return string.Empty;
             }