From 5a2ee843105cd998776ad6766d8f86ab2e4f2aab Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Sun, 26 Jul 2020 22:24:36 -0700 Subject: [PATCH] Fix TypeWithAnnotations.ToTypeWithState() for (untyped) null literal --- .../OverloadResolution/MethodTypeInference.cs | 2 +- .../Portable/Symbols/TypeWithAnnotations.cs | 9 +- .../Semantics/NullableReferenceTypesTests.cs | 162 +++++++++++++++++- 3 files changed, 163 insertions(+), 10 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index f621cf43e9a41..161f40c435ff2 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -1542,7 +1542,7 @@ private bool ExactOrBoundsNullableInference(ExactOrBoundsKind kind, TypeWithAnno return false; // True if the type is nullable. - bool isNullableOnly(TypeWithAnnotations type) + static bool isNullableOnly(TypeWithAnnotations type) => type.NullableAnnotation.IsAnnotated(); } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs index 45ca7352ec912..5a6c86e5b2f8f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs @@ -772,11 +772,6 @@ internal bool IsSameAs(TypeWithAnnotations other) /// internal TypeWithState ToTypeWithState() { - if (Type is null) - { - return default; - } - // This operation reflects reading from an lvalue, which produces an rvalue. // Reading from a variable of a type parameter (that could be substituted with a nullable type), but which // cannot itself be annotated (because it isn't known to be a reference type), may yield a null value @@ -785,6 +780,10 @@ internal TypeWithState ToTypeWithState() static NullableFlowState getFlowState(TypeSymbol type, NullableAnnotation annotation) { + if (type is null) + { + return annotation.IsAnnotated() ? NullableFlowState.MaybeNull : NullableFlowState.NotNull; + } if (type.IsPossiblyNullableReferenceTypeTypeParameter()) { return annotation switch { NullableAnnotation.Annotated => NullableFlowState.MaybeDefault, NullableAnnotation.NotAnnotated => NullableFlowState.MaybeNull, _ => NullableFlowState.NotNull }; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 2f4670f0ceabf..b7706c05f7546 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -51082,12 +51082,12 @@ static void G(string x) new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( - // (9,54): warning CS8603: Possible null reference return. + // (9,9): warning CS8602: Dereference of a possibly null reference. // F(() => { if (x.Length > 0) return x; return null; }).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(9, 54), - // (10,45): warning CS8603: Possible null reference return. + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => { if (x.Length > 0) return x; return null; })").WithLocation(9, 9), + // (10,9): warning CS8602: Dereference of a possibly null reference. // F(() => { if (x.Length == 0) return null; return x; }).ToString(); - Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(10, 45)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => { if (x.Length == 0) return null; return x; })").WithLocation(10, 9)); } [Fact] @@ -133331,6 +133331,160 @@ internal interface IB : IA { } comp.VerifyEmitDiagnostics(); } + [Fact] + [WorkItem(46342, "https://github.com/dotnet/roslyn/issues/46342")] + public void LambdaNullReturn_01() + { + var source = +@"#nullable enable +using System; +class Program +{ + static void F(Func f) + { + } + static void M(bool b, T t) where T : class + { + F(() => + { + if (b) return null; + return t; + }); + } +}"; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + [WorkItem(46342, "https://github.com/dotnet/roslyn/issues/46342")] + public void LambdaNullReturn_02() + { + var source = +@"#nullable enable +using System; +class Program +{ + static void F(Func f) + { + } + static void M(bool b, T t) where T : class? + { + F(() => + { + if (b) return null; + return t; + }); + } +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + [WorkItem(46342, "https://github.com/dotnet/roslyn/issues/46342")] + public void LambdaNullReturn_03() + { + var source = +@"#nullable enable +using System; +class Program +{ + static void F(Func f) + { + } + static void M(T? t) where T : class + { + F(() => + { + if (t is null) return null; + return t; + }); + } +}"; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + [WorkItem(46342, "https://github.com/dotnet/roslyn/issues/46342")] + public void LambdaNullReturn_04() + { + var source = +@"#nullable enable +using System; +class Program +{ + static void F(Func f) + { + } + static void M(T? t) where T : class? + { + F(() => + { + if (t is null) return null; + return t; + }); + } +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + [WorkItem(46342, "https://github.com/dotnet/roslyn/issues/46342")] + public void LambdaNullReturn_05() + { + var source = +@"#nullable enable +using System; +using System.Threading.Tasks; +class Program +{ + static void F(Func> f) + { + } + static void M(T? t) where T : class + { + F(async () => + { + await Task.Yield(); + if (t is null) return null; + return t; + }); + } +}"; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + [WorkItem(46342, "https://github.com/dotnet/roslyn/issues/46342")] + public void LambdaNullReturn_06() + { + var source = +@"#nullable enable +using System; +using System.Threading.Tasks; +class Program +{ + static void F(Func> f) + { + } + static void M(T? t) where T : class? + { + F(async () => + { + await Task.Yield(); + if (t is null) return null; + return t; + }); + } +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); + comp.VerifyEmitDiagnostics(); + } + [Fact] [WorkItem(45862, "https://github.com/dotnet/roslyn/issues/45862")] public void Issue_45862()