Nullable: System.IO (dotnet/coreclr#23732)
authorStephen Toub <stoub@microsoft.com>
Tue, 9 Apr 2019 16:10:28 +0000 (12:10 -0400)
committerGitHub <noreply@github.com>
Tue, 9 Apr 2019 16:10:28 +0000 (12:10 -0400)
* Nullable: System.IO

Everything exception StreamReader, StreamWriter, BinaryReader, BinaryWriter, which are waiting for some changes in master to propagate over to the feature branch.

* Address PR feedback

Commit migrated from https://github.com/dotnet/coreclr/commit/5ce35bf3d4456a81e22b6a74a03978a1a3abd75d

24 files changed:
src/libraries/System.Private.CoreLib/src/System/IO/DisableMediaInsertionPrompt.cs
src/libraries/System.Private.CoreLib/src/System/IO/DriveInfoInternal.Unix.cs
src/libraries/System.Private.CoreLib/src/System/IO/DriveInfoInternal.Windows.cs
src/libraries/System.Private.CoreLib/src/System/IO/EncodingCache.cs
src/libraries/System.Private.CoreLib/src/System/IO/Error.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileAccess.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileMode.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileOptions.cs
src/libraries/System.Private.CoreLib/src/System/IO/FileShare.cs
src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs
src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs
src/libraries/System.Private.CoreLib/src/System/IO/Path.cs
src/libraries/System.Private.CoreLib/src/System/IO/PathHelper.Windows.cs
src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Unix.cs
src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs
src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs
src/libraries/System.Private.CoreLib/src/System/IO/PersistedFiles.Names.Unix.cs
src/libraries/System.Private.CoreLib/src/System/IO/PersistedFiles.Unix.cs
src/libraries/System.Private.CoreLib/src/System/IO/SeekOrigin.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/UnmanagedMemoryAccessor.cs
src/libraries/System.Private.CoreLib/src/System/ParamsArray.cs
src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs

index a3a2d29..cfb4b66 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 #if MS_IO_REDIST
 using System;
 
index 78ef957..c4eba1c 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Text;
 
index 47dbcdd..6d6c2ea 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Text;
 
@@ -51,7 +52,7 @@ namespace System.IO
         {
             Debug.Assert(driveName != null);
 
-            string name;
+            string? name;
 
             if (driveName.Length == 1)
             {
index 53379bc..fb3795e 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Text;
 
 namespace System.IO
index 1e319a0..db80954 100644 (file)
@@ -2,11 +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.Runtime.InteropServices;
-using System.Text;
-using System.Globalization;
-
+#nullable enable
 namespace System.IO
 {
     /// <summary>
index 1b70bae..2fd7408 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System;
 
 namespace System.IO
index 77f2fe6..39c74e5 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 namespace System.IO
 {
     // Contains constants for specifying how the OS should open a file.
index ae8396a..b11b9bb 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System;
 using System.Runtime.InteropServices;
 
index e9b9b5e..12dc6e6 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System;
 
 namespace System.IO
index ecf71e6..f8c93d6 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -77,7 +78,7 @@ namespace System.IO
             // Get the temp path from the TMPDIR environment variable.
             // If it's not set, just return the default path.
             // If it is, return it, ensuring it ends with a slash.
-            string path = Environment.GetEnvironmentVariable(TempEnvVar);
+            string? path = Environment.GetEnvironmentVariable(TempEnvVar);
             return
                 string.IsNullOrEmpty(path) ? DefaultTempPath :
                 PathInternal.IsDirectorySeparator(path[path.Length - 1]) ? path :
@@ -103,7 +104,7 @@ namespace System.IO
             return Encoding.UTF8.GetString(name, 0, name.Length - 1); // trim off the trailing '\0'
         }
 
-        public static bool IsPathRooted(string path)
+        public static bool IsPathRooted(string? path)
         {
             if (path == null)
                 return false;
@@ -119,7 +120,7 @@ namespace System.IO
         /// <summary>
         /// Returns the path root or null if path is empty or null.
         /// </summary>
-        public static string GetPathRoot(string path)
+        public static string? GetPathRoot(string? path)
         {
             if (PathInternal.IsEffectivelyEmpty(path)) return null;
 
index ddfd796..71a986e 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Text;
 
@@ -83,7 +84,7 @@ namespace System.IO
                 return basePath;
 
             int length = path.Length;
-            string combinedPath = null;
+            string? combinedPath = null;
 
             if ((length >= 1 && PathInternal.IsDirectorySeparator(path[0])))
             {
@@ -189,7 +190,7 @@ namespace System.IO
 
         // Tests if the given path contains a root. A path is considered rooted
         // if it starts with a backslash ("\") or a valid drive letter and a colon (":").
-        public static bool IsPathRooted(string path)
+        public static bool IsPathRooted(string? path)
         {
             return path != null && IsPathRooted(path.AsSpan());
         }
@@ -210,13 +211,13 @@ namespace System.IO
         // and "\\server\share" (a UNC path for a given server and share name).
         // The resulting string is null if path is null. If the path is empty or
         // only contains whitespace characters an ArgumentException gets thrown.
-        public static string GetPathRoot(string path)
+        public static string? GetPathRoot(string? path)
         {
             if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
                 return null;
 
             ReadOnlySpan<char> result = GetPathRoot(path.AsSpan());
-            if (path.Length == result.Length)
+            if (path!.Length == result.Length)
                 return PathInternal.NormalizeDirectorySeparators(path);
 
             return PathInternal.NormalizeDirectorySeparators(result.ToString());
index 23da520..db491bf 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -45,7 +46,7 @@ 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)
+        public static string? ChangeExtension(string? path, string? extension) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             if (path == null)
                 return null;
@@ -98,7 +99,7 @@ namespace System.IO
         /// <remarks>
         /// Directory separators are normalized in the returned string.
         /// </remarks>
-        public static string GetDirectoryName(string path)
+        public static string? GetDirectoryName(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             if (path == null || PathInternal.IsEffectivelyEmpty(path.AsSpan()))
                 return null;
@@ -146,7 +147,7 @@ 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)
+        public static string? GetExtension(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             if (path == null)
                 return null;
@@ -185,7 +186,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>
-        public static string GetFileName(string path)
+        public static string? GetFileName(string? path)
         {
             if (path == null)
                 return null;
@@ -216,7 +217,7 @@ namespace System.IO
             return path;
         }
 
-        public static string GetFileNameWithoutExtension(string path)
+        public static string? GetFileNameWithoutExtension(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
         {
             if (path == null)
                 return null;
@@ -290,7 +291,7 @@ namespace System.IO
         /// Tests if a path's file name includes a file extension. A trailing period
         /// is not considered an extension.
         /// </summary>
-        public static bool HasExtension(string path)
+        public static bool HasExtension(string? path)
         {
             if (path != null)
             {
@@ -433,12 +434,12 @@ namespace System.IO
             return JoinInternal(path1, path2, path3);
         }
 
-        public static string Join(string path1, string path2)
+        public static string Join(string? path1, string? path2)
         {
             return Join(path1.AsSpan(), path2.AsSpan());
         }
 
-        public static string Join(string path1, string path2, string path3)
+        public static string Join(string? path1, string? path2, string? path3)
         {
             return Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan());
         }
index a30ead1..f494412 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -126,7 +127,7 @@ namespace System.IO
             }
         }
 
-        internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
+        internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string? originalPath)
         {
             // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To
             // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls.
index fae309b..1888c85 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Text;
 using System.Runtime.InteropServices;
@@ -89,7 +90,7 @@ namespace System.IO
         /// For unix, this is empty or null. For Windows, this is empty, null, or 
         /// just spaces ((char)32).
         /// </summary>
-        internal static bool IsEffectivelyEmpty(string path)
+        internal static bool IsEffectivelyEmpty(string? path)
         {
             return string.IsNullOrEmpty(path);
         }
index 5e9e613..99aa021 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Runtime.CompilerServices;
 using System.Text;
 
@@ -70,7 +71,7 @@ namespace System.IO
             return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
         }
 
-        internal static bool EndsWithPeriodOrSpace(string path)
+        internal static bool EndsWithPeriodOrSpace(string? path)
         {
             if (string.IsNullOrEmpty(path))
                 return false;
@@ -86,7 +87,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>
-        internal static string EnsureExtendedPrefixIfNeeded(string path)
+        internal static string? EnsureExtendedPrefixIfNeeded(string? path)
         {
             if (path != null && (path.Length >= MaxShortPath || EndsWithPeriodOrSpace(path)))
             {
@@ -103,7 +104,7 @@ namespace System.IO
         /// Adds the extended path prefix (\\?\) if not already a device path, IF the path is not relative,
         /// AND the path is more than 259 characters. (> MAX_PATH + null)
         /// </summary>
-        internal static string EnsureExtendedPrefixOverMaxPath(string path)
+        internal static string? EnsureExtendedPrefixOverMaxPath(string? path)
         {
             if (path != null && path.Length >= MaxShortPath)
             {
index c6e1de4..549a2d1 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Text;
 
index 8984f1a..03bfc02 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 namespace System.IO
 {
     internal static partial class PersistedFiles
index d8064af..8dfa2f1 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 
@@ -9,7 +10,7 @@ namespace System.IO
 {
     internal static partial class PersistedFiles
     {
-        private static string s_userProductDirectory;
+        private static string? s_userProductDirectory;
 
         /// <summary>
         /// Get the location of where to persist information for a particular aspect of the framework,
@@ -24,7 +25,7 @@ namespace System.IO
                 EnsureUserDirectories();
             }
 
-            return Path.Combine(s_userProductDirectory, featureName);
+            return Path.Combine(s_userProductDirectory!, featureName);
         }
 
         /// <summary>
@@ -41,7 +42,7 @@ namespace System.IO
                 EnsureUserDirectories();
             }
 
-            return Path.Combine(s_userProductDirectory, featureName, subFeatureName);
+            return Path.Combine(s_userProductDirectory!, featureName, subFeatureName);
         }
 
         /// <summary>
@@ -60,12 +61,12 @@ namespace System.IO
                 EnsureUserDirectories();
             }
 
-            return Path.Combine(s_userProductDirectory, Path.Combine(featurePathParts));
+            return Path.Combine(s_userProductDirectory!, Path.Combine(featurePathParts));
         }
 
         private static void EnsureUserDirectories()
         {
-            string userHomeDirectory = GetHomeDirectory();
+            string? userHomeDirectory = GetHomeDirectory();
 
             if (string.IsNullOrEmpty(userHomeDirectory))
             {
@@ -80,11 +81,11 @@ namespace System.IO
 
         /// <summary>Gets the current user's home directory.</summary>
         /// <returns>The path to the home directory, or null if it could not be determined.</returns>
-        internal static string GetHomeDirectory()
+        internal static string? GetHomeDirectory()
         {
             // First try to get the user's home directory from the HOME environment variable.
             // This should work in most cases.
-            string userHomeDirectory = Environment.GetEnvironmentVariable("HOME");
+            string? userHomeDirectory = Environment.GetEnvironmentVariable("HOME");
             if (!string.IsNullOrEmpty(userHomeDirectory))
                 return userHomeDirectory;
 
@@ -123,7 +124,7 @@ namespace System.IO
         /// <param name="bufLen">The length of <paramref name="buf"/>.</param>
         /// <param name="path">The resulting path; null if the user didn't have an entry.</param>
         /// <returns>true if the call was successful (path may still be null); false is a larger buffer is needed.</returns>
-        private static unsafe bool TryGetHomeDirectoryFromPasswd(byte* buf, int bufLen, out string path)
+        private static unsafe bool TryGetHomeDirectoryFromPasswd(byte* buf, int bufLen, out string? path)
         {
             // Call getpwuid_r to get the passwd struct
             Interop.Sys.Passwd passwd;
index 3798a0c..e1da4d5 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 namespace System.IO
 {
     // Provides seek reference points.  To seek to the end of a stream,
index c1a9fd6..7a43f6e 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -178,7 +179,7 @@ namespace System.IO
         // contain the terminating carriage return and/or line feed. The returned
         // value is null if the end of the input stream has been reached.
         //
-        public virtual string ReadLine()
+        public virtual string? ReadLine()
         {
             StringBuilder sb = new StringBuilder();
             while (true)
@@ -205,11 +206,11 @@ namespace System.IO
         }
 
         #region Task based Async APIs
-        public virtual Task<string> ReadLineAsync()
+        public virtual Task<string?> ReadLineAsync()
         {
-            return Task<string>.Factory.StartNew(state =>
+            return Task<string?>.Factory.StartNew(state =>
             {
-                return ((TextReader)state).ReadLine();
+                return ((TextReader)state!).ReadLine(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             },
             this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
@@ -256,7 +257,7 @@ namespace System.IO
                 ReadAsync(array.Array, array.Offset, array.Count) :
                 Task<int>.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextReader, Memory<char>>)state;
+                    var t = (Tuple<TextReader, Memory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                     return t.Item1.Read(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
 
@@ -265,7 +266,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;
+                var t = (Tuple<TextReader, Memory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 return t.Item1.Read(t.Item2.Span);
             },
             tuple, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
@@ -294,7 +295,7 @@ namespace System.IO
                 ReadBlockAsync(array.Array, array.Offset, array.Count) :
                 Task<int>.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextReader, Memory<char>>)state;
+                    var t = (Tuple<TextReader, Memory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                     return t.Item1.ReadBlock(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
 
@@ -320,7 +321,7 @@ namespace System.IO
                 return 0;
             }
 
-            public override string ReadLine()
+            public override string? ReadLine()
             {
                 return null;
             }
@@ -367,7 +368,7 @@ namespace System.IO
             public override int ReadBlock(char[] buffer, int index, int count) => _in.ReadBlock(buffer, index, count);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override string ReadLine() => _in.ReadLine();
+            public override string? ReadLine() => _in.ReadLine();
 
             [MethodImpl(MethodImplOptions.Synchronized)]
             public override string ReadToEnd() => _in.ReadToEnd();
@@ -377,7 +378,7 @@ namespace System.IO
             //
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override Task<string> ReadLineAsync() => Task.FromResult(ReadLine());
+            public override Task<string?> ReadLineAsync() => Task.FromResult(ReadLine());
 
             [MethodImpl(MethodImplOptions.Synchronized)]
             public override Task<string> ReadToEndAsync() => Task.FromResult(ReadToEnd());
index baf53b4..d66ee43 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System.Text;
 using System.Threading;
 using System.Globalization;
@@ -36,14 +37,14 @@ namespace System.IO
         private string CoreNewLineStr = Environment.NewLine;
 
         // Can be null - if so, ask for the Thread's CurrentCulture every time.
-        private IFormatProvider _internalFormatProvider;
+        private IFormatProvider? _internalFormatProvider;
 
         protected TextWriter()
         {
             _internalFormatProvider = null;  // Ask for CurrentCulture all the time.
         }
 
-        protected TextWriter(IFormatProvider formatProvider)
+        protected TextWriter(IFormatProvider? formatProvider)
         {
             _internalFormatProvider = formatProvider;
         }
@@ -117,7 +118,7 @@ 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
+        public virtual string? NewLine // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384
         {
             get { return CoreNewLineStr; }
             set
@@ -268,7 +269,7 @@ namespace System.IO
         // Writes a string to the text stream. If the given string is null, nothing
         // is written to the text stream.
         //
-        public virtual void Write(string value)
+        public virtual void Write(string? value)
         {
             if (value != null)
             {
@@ -282,7 +283,7 @@ namespace System.IO
         // string representation, and the resulting string is then written to the
         // output stream.
         //
-        public virtual void Write(object value)
+        public virtual void Write(object? value)
         {
             if (value != null)
             {
@@ -300,7 +301,7 @@ namespace System.IO
         /// StringBuilder.GetChunks() method to avoid creating the intermediate string
         /// </summary>
         /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
-        public virtual void Write(StringBuilder value)
+        public virtual void Write(StringBuilder? value)
         {
             if (value != null)
             {
@@ -312,7 +313,7 @@ namespace System.IO
         // Writes out a formatted string.  Uses the same semantics as
         // string.Format.
         //
-        public virtual void Write(string format, object arg0)
+        public virtual void Write(string format, object? arg0)
         {
             Write(string.Format(FormatProvider, format, arg0));
         }
@@ -320,7 +321,7 @@ namespace System.IO
         // Writes out a formatted string.  Uses the same semantics as
         // string.Format.
         //
-        public virtual void Write(string format, object arg0, object arg1)
+        public virtual void Write(string format, object? arg0, object? arg1)
         {
             Write(string.Format(FormatProvider, format, arg0, arg1));
         }
@@ -328,7 +329,7 @@ namespace System.IO
         // Writes out a formatted string.  Uses the same semantics as
         // string.Format.
         //
-        public virtual void Write(string format, object arg0, object arg1, object arg2)
+        public virtual void Write(string format, object? arg0, object? arg1, object? arg2)
         {
             Write(string.Format(FormatProvider, format, arg0, arg1, arg2));
         }
@@ -336,7 +337,7 @@ namespace System.IO
         // Writes out a formatted string.  Uses the same semantics as
         // string.Format.
         //
-        public virtual void Write(string format, params object[] arg)
+        public virtual void Write(string format, params object?[] arg)
         {
             Write(string.Format(FormatProvider, format, arg));
         }
@@ -464,7 +465,7 @@ namespace System.IO
 
         // Writes a string followed by a line terminator to the text stream.
         //
-        public virtual void WriteLine(string value)
+        public virtual void WriteLine(string? value)
         {
             if (value != null)
             {
@@ -477,7 +478,7 @@ namespace System.IO
         /// Equivalent to WriteLine(stringBuilder.ToString()) however it uses the
         /// StringBuilder.GetChunks() method to avoid creating the intermediate string
         /// </summary>
-        public virtual void WriteLine(StringBuilder value)
+        public virtual void WriteLine(StringBuilder? value)
         {
             Write(value);
             WriteLine();
@@ -486,7 +487,7 @@ namespace System.IO
         // Writes the text representation of an object followed by a line
         // terminator to the text stream.
         //
-        public virtual void WriteLine(object value)
+        public virtual void WriteLine(object? value)
         {
             if (value == null)
             {
@@ -510,7 +511,7 @@ namespace System.IO
         // Writes out a formatted string and a new line.  Uses the same
         // semantics as string.Format.
         //
-        public virtual void WriteLine(string format, object arg0)
+        public virtual void WriteLine(string format, object? arg0)
         {
             WriteLine(string.Format(FormatProvider, format, arg0));
         }
@@ -518,7 +519,7 @@ namespace System.IO
         // Writes out a formatted string and a new line.  Uses the same
         // semantics as string.Format.
         //
-        public virtual void WriteLine(string format, object arg0, object arg1)
+        public virtual void WriteLine(string format, object? arg0, object? arg1)
         {
             WriteLine(string.Format(FormatProvider, format, arg0, arg1));
         }
@@ -526,7 +527,7 @@ namespace System.IO
         // Writes out a formatted string and a new line.  Uses the same
         // semantics as string.Format.
         //
-        public virtual void WriteLine(string format, object arg0, object arg1, object arg2)
+        public virtual void WriteLine(string format, object? arg0, object? arg1, object? arg2)
         {
             WriteLine(string.Format(FormatProvider, format, arg0, arg1, arg2));
         }
@@ -534,7 +535,7 @@ namespace System.IO
         // Writes out a formatted string and a new line.  Uses the same
         // semantics as string.Format.
         //
-        public virtual void WriteLine(string format, params object[] arg)
+        public virtual void WriteLine(string format, params object?[] arg)
         {
             WriteLine(string.Format(FormatProvider, format, arg));
         }
@@ -545,18 +546,18 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, char>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, char>)state;
+                var t = (Tuple<TextWriter, char>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 t.Item1.Write(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
 
-        public virtual Task WriteAsync(string value)
+        public virtual Task WriteAsync(string? value)
         {
-            var tuple = new Tuple<TextWriter, string>(this, value);
+            var tuple = new Tuple<TextWriter, string?>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, string>)state;
+                var t = (Tuple<TextWriter, string?>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 t.Item1.Write(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -567,7 +568,7 @@ namespace System.IO
         /// StringBuilder.GetChunks() method to avoid creating the intermediate string
         /// </summary>
         /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
-        public virtual Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+        public virtual Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default)
         {
             return
                 cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
@@ -598,7 +599,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;
+                var t = (Tuple<TextWriter, char[], int, int>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 t.Item1.Write(t.Item2, t.Item3, t.Item4);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -610,7 +611,7 @@ namespace System.IO
                 WriteAsync(array.Array, array.Offset, array.Count) :
                 Task.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state;
+                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                     t.Item1.Write(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
 
@@ -619,18 +620,18 @@ namespace System.IO
             var tuple = new Tuple<TextWriter, char>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, char>)state;
+                var t = (Tuple<TextWriter, char>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 t.Item1.WriteLine(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
 
-        public virtual Task WriteLineAsync(string value)
+        public virtual Task WriteLineAsync(string? value)
         {
-            var tuple = new Tuple<TextWriter, string>(this, value);
+            var tuple = new Tuple<TextWriter, string?>(this, value);
             return Task.Factory.StartNew(state =>
             {
-                var t = (Tuple<TextWriter, string>)state;
+                var t = (Tuple<TextWriter, string?>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 t.Item1.WriteLine(t.Item2);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -641,7 +642,7 @@ namespace System.IO
         /// StringBuilder.GetChunks() method to avoid creating the intermediate string
         /// </summary>
         /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
-        public virtual Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+        public virtual Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default)
         {
             return
                 cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
@@ -673,7 +674,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;
+                var t = (Tuple<TextWriter, char[], int, int>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                 t.Item1.WriteLine(t.Item2, t.Item3, t.Item4);
             },
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
@@ -685,7 +686,7 @@ namespace System.IO
                 WriteLineAsync(array.Array, array.Offset, array.Count) :
                 Task.Factory.StartNew(state =>
                 {
-                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state;
+                    var t = (Tuple<TextWriter, ReadOnlyMemory<char>>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
                     t.Item1.WriteLine(t.Item2.Span);
                 }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
 
@@ -698,7 +699,7 @@ namespace System.IO
         {
             return Task.Factory.StartNew(state =>
             {
-                ((TextWriter)state).Flush();
+                ((TextWriter)state!).Flush(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
             },
             this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
@@ -722,7 +723,7 @@ namespace System.IO
             {
             }
 
-            public override void Write(string value)
+            public override void Write(string? value)
             {
             }
 
@@ -732,11 +733,11 @@ namespace System.IO
             }
 
             // Not strictly necessary, but for perf reasons
-            public override void WriteLine(string value)
+            public override void WriteLine(string? value)
             {
             }
 
-            public override void WriteLine(object value)
+            public override void WriteLine(object? value)
             {
             }
 
@@ -762,11 +763,11 @@ namespace System.IO
                 _out = t;
             }
 
-            public override Encoding Encoding =>  _out.Encoding;
+            public override Encoding Encoding => _out.Encoding;
 
             public override IFormatProvider FormatProvider => _out.FormatProvider;
 
-            public override string NewLine
+            public override string? NewLine
             {
                 [MethodImpl(MethodImplOptions.Synchronized)]
                 get { return _out.NewLine; }
@@ -825,25 +826,25 @@ namespace System.IO
             public override void Write(decimal value) => _out.Write(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(string value) => _out.Write(value);
+            public override void Write(string? value) => _out.Write(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(StringBuilder value) => _out.Write(value);
+            public override void Write(StringBuilder? value) => _out.Write(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(object value) => _out.Write(value);
+            public override void Write(object? value) => _out.Write(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(string format, object arg0) => _out.Write(format, arg0);
+            public override void Write(string format, object? arg0) => _out.Write(format, arg0);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(string format, object arg0, object arg1) => _out.Write(format, arg0, arg1);
+            public override void Write(string format, object? arg0, object? arg1) => _out.Write(format, arg0, arg1);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(string format, object arg0, object arg1, object arg2) => _out.Write(format, arg0, arg1, arg2);
+            public override void Write(string format, object? arg0, object? arg1, object? arg2) => _out.Write(format, arg0, arg1, arg2);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void Write(string format, object[] arg) => _out.Write(format, arg);
+            public override void Write(string format, object?[] arg) => _out.Write(format, arg);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
             public override void WriteLine() => _out.WriteLine();
@@ -885,25 +886,25 @@ namespace System.IO
             public override void WriteLine(double value) => _out.WriteLine(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(string value) => _out.WriteLine(value);
+            public override void WriteLine(string? value) => _out.WriteLine(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(StringBuilder value) => _out.WriteLine(value);
+            public override void WriteLine(StringBuilder? value) => _out.WriteLine(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(object value) => _out.WriteLine(value);
+            public override void WriteLine(object? value) => _out.WriteLine(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(string format, object arg0) => _out.WriteLine(format, arg0);
+            public override void WriteLine(string format, object? arg0) => _out.WriteLine(format, arg0);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(string format, object arg0, object arg1) => _out.WriteLine(format, arg0, arg1);
+            public override void WriteLine(string format, object? arg0, object? arg1) => _out.WriteLine(format, arg0, arg1);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(string format, object arg0, object arg1, object arg2) => _out.WriteLine(format, arg0, arg1, arg2);
+            public override void WriteLine(string format, object? arg0, object? arg1, object? arg2) => _out.WriteLine(format, arg0, arg1, arg2);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override void WriteLine(string format, object[] arg) => _out.WriteLine(format, arg);
+            public override void WriteLine(string format, object?[] arg) => _out.WriteLine(format, arg);
 
             //
             // On SyncTextWriter all APIs should run synchronously, even the async ones.
@@ -924,14 +925,14 @@ namespace System.IO
             }
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override Task WriteAsync(string value)
+            public override Task WriteAsync(string? value)
             {
                 Write(value);
                 return Task.CompletedTask;
             }
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+            public override Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default)
             {
                 if (cancellationToken.IsCancellationRequested)
                 {
@@ -988,14 +989,14 @@ namespace System.IO
             }
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override Task WriteLineAsync(string value)
+            public override Task WriteLineAsync(string? value)
             {
                 WriteLine(value);
                 return Task.CompletedTask;
             }
 
             [MethodImpl(MethodImplOptions.Synchronized)]
-            public override Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+            public override Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default)
             {
                 if (cancellationToken.IsCancellationRequested)
                 {
index 1247ad6..4e66b7c 100644 (file)
@@ -13,8 +13,7 @@
 **
 ===========================================================*/
 
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
+#nullable enable
 using System.Runtime.InteropServices;
 using Internal.Runtime.CompilerServices;
 
@@ -25,7 +24,7 @@ namespace System.IO
     /// this gives better throughput; benchmarks showed about 12-15% better.
     public class UnmanagedMemoryAccessor : IDisposable
     {
-        private SafeBuffer _buffer;
+        private SafeBuffer _buffer = null!; // initialized in helper called by ctor
         private long _offset;
         private long _capacity;
         private FileAccess _access;
index 043ee67..91b2bd1 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 namespace System
 {
     internal readonly struct ParamsArray
@@ -9,19 +10,19 @@ namespace System
         // Sentinel fixed-length arrays eliminate the need for a "count" field keeping this
         // struct down to just 4 fields. These are only used for their "Length" property,
         // that is, their elements are never set or referenced.
-        private static readonly object[] s_oneArgArray = new object[1];
-        private static readonly object[] s_twoArgArray = new object[2];
-        private static readonly object[] s_threeArgArray = new object[3];
+        private static readonly object?[] s_oneArgArray = new object?[1];
+        private static readonly object?[] s_twoArgArray = new object?[2];
+        private static readonly object?[] s_threeArgArray = new object?[3];
 
-        private readonly object _arg0;
-        private readonly object _arg1;
-        private readonly object _arg2;
+        private readonly object? _arg0;
+        private readonly object? _arg1;
+        private readonly object? _arg2;
 
         // After construction, the first three elements of this array will never be accessed
         // because the indexer will retrieve those values from arg0, arg1, and arg2.
-        private readonly object[] _args;
+        private readonly object?[] _args;
 
-        public ParamsArray(object arg0)
+        public ParamsArray(object? arg0)
         {
             _arg0 = arg0;
             _arg1 = null;
@@ -31,7 +32,7 @@ namespace System
             _args = s_oneArgArray;
         }
 
-        public ParamsArray(object arg0, object arg1)
+        public ParamsArray(object? arg0, object? arg1)
         {
             _arg0 = arg0;
             _arg1 = arg1;
@@ -41,7 +42,7 @@ namespace System
             _args = s_twoArgArray;
         }
 
-        public ParamsArray(object arg0, object arg1, object arg2)
+        public ParamsArray(object? arg0, object? arg1, object? arg2)
         {
             _arg0 = arg0;
             _arg1 = arg1;
@@ -51,7 +52,7 @@ namespace System
             _args = s_threeArgArray;
         }
 
-        public ParamsArray(object[] args)
+        public ParamsArray(object?[] args)
         {
             int len = args.Length;
             _arg0 = len > 0 ? args[0] : null;
@@ -65,12 +66,12 @@ namespace System
             get { return _args.Length; }
         }
 
-        public object this[int index]
+        public object? this[int index]
         {
             get { return index == 0 ? _arg0 : GetAtSlow(index); }
         }
 
-        private object GetAtSlow(int index)
+        private object? GetAtSlow(int index)
         {
             if (index == 1)
                 return _arg1;
index e05e966..41b16cf 100644 (file)
@@ -1654,7 +1654,7 @@ namespace System.Text
                 //
                 // Start of parsing of optional formatting parameter.
                 //
-                object arg = args[index];
+                object? arg = args[index];
                 string? itemFormat = null;
                 ReadOnlySpan<char> itemFormatSpan = default; // used if itemFormat is null
                 // Is current character a colon? which indicates start of formatting parameter.