// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using static Microsoft.CodeAnalysis.CSharp.Symbols.FlowAnalysisAnnotations; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics { [CompilerTrait(CompilerFeature.NullableReferenceTypes)] public class NullableReferenceTypesTests : CSharpTestBase { private const string Tuple2NonNullable = @" namespace System { #nullable enable // struct with two values public struct ValueTuple where T1 : notnull where T2 : notnull { public T1 Item1; public T2 Item2; public ValueTuple(T1 item1, T2 item2) { this.Item1 = item1; this.Item2 = item2; } public override string ToString() { return """"; } } }"; private const string TupleRestNonNullable = @" namespace System { #nullable enable public struct ValueTuple where T1 : notnull where T2 : notnull where T3 : notnull where T4 : notnull where T5 : notnull where T6 : notnull where T7 : notnull { public T1 Item1; public T2 Item2; public T3 Item3; public T4 Item4; public T5 Item5; public T6 Item6; public T7 Item7; public TRest Rest; public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) { Item1 = item1; Item2 = item2; Item3 = item3; Item4 = item4; Item5 = item5; Item6 = item6; Item7 = item7; Rest = rest; } public override string ToString() { return base.ToString(); } } }"; private CSharpCompilation CreateNullableCompilation(CSharpTestSource source, IEnumerable references = null) { return CreateCompilation(source, options: WithNonNullTypesTrue(), references: references); } [Fact, WorkItem(33982, "https://github.com/dotnet/roslyn/issues/33982")] public void AssigningNullToRefLocalIsSafetyWarning() { var comp = CreateCompilation(@" class C { void M(ref string s1, ref string s2) { s1 = null; // 1 s1.ToString(); // 2 ref string s3 = ref s2; s3 = null; // 3 s3.ToString(); // 4 ref string s4 = ref s2; s4 ??= null; // 5 s4.ToString(); // 6 ref string s5 = ref s2; M2(out s5); // 7 s5.ToString(); // 8 } void M2(out string? x) => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // s1 = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 14), // (7,9): warning CS8602: Possible dereference of a null reference. // s1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(7, 9), // (10,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // s3 = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 14), // (11,9): warning CS8602: Possible dereference of a null reference. // s3.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(11, 9), // (14,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // s4 ??= null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 16), // (15,9): warning CS8602: Possible dereference of a null reference. // s4.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(15, 9), // (18,16): warning CS8601: Possible null reference assignment. // M2(out s5); // 7 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s5").WithLocation(18, 16), // (19,9): warning CS8602: Possible dereference of a null reference. // s5.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(19, 9) ); } [Fact, WorkItem(33365, "https://github.com/dotnet/roslyn/issues/33365")] public void AssigningNullToConditionalRefLocal() { var comp = CreateCompilation(@" class C { void M(ref string s1, ref string s2, bool b) { (b ? ref s1 : ref s1) = null; // 1 s1.ToString(); ref string s3 = ref s2; (b ? ref s3 : ref s3) = null; // 2 s3.ToString(); ref string s4 = ref s2; (b ? ref s4 : ref s4) ??= null; // 3 s4.ToString(); ref string s5 = ref s2; M2(out (b ? ref s5 : ref s5)); // 4 s5.ToString(); } void M2(out string? x) => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,33): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref s1 : ref s1) = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 33), // (10,33): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref s3 : ref s3) = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 33), // (14,35): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref s4 : ref s4) ??= null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 35), // (18,17): warning CS8601: Possible null reference assignment. // M2(out (b ? ref s5 : ref s5)); // 4 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "b ? ref s5 : ref s5").WithLocation(18, 17) ); } [Fact, WorkItem(33365, "https://github.com/dotnet/roslyn/issues/33365")] public void AssigningNullToConditionalRefLocal_NullableLocals() { var comp = CreateCompilation(@" class C { void M(ref string? s1, ref string? s2, bool b) { (b ? ref s1 : ref s1) = null; s1.ToString(); // 1 ref string? s3 = ref s2; (b ? ref s3 : ref s3) = null; s3.ToString(); // 2 ref string? s4 = ref s2; (b ? ref s4 : ref s4) ??= null; s4.ToString(); // 3 ref string? s5 = ref s2; M2(out (b ? ref s5 : ref s5)); s5.ToString(); // 4 } void M2(out string? x) => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Possible dereference of a null reference. // s1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(7, 9), // (11,9): warning CS8602: Possible dereference of a null reference. // s3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(11, 9), // (15,9): warning CS8602: Possible dereference of a null reference. // s4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(15, 9), // (19,9): warning CS8602: Possible dereference of a null reference. // s5.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(19, 9) ); } [Fact, WorkItem(33365, "https://github.com/dotnet/roslyn/issues/33365")] public void AssigningNullToConditionalRefLocal_NullableLocals_NonNullValues() { var comp = CreateCompilation(@" class C { void M(ref string? s1, ref string? s2, bool b) { (b ? ref s1 : ref s1) = """"; s1.ToString(); // 1 ref string? s3 = ref s2; (b ? ref s3 : ref s3) = """"; s3.ToString(); // 2 ref string? s4 = ref s2; (b ? ref s4 : ref s4) ??= """"; s4.ToString(); // 3 ref string? s5 = ref s2; M2(out (b ? ref s5 : ref s5)); s5.ToString(); // 4 } void M2(out string x) => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Possible dereference of a null reference. // s1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(7, 9), // (11,9): warning CS8602: Possible dereference of a null reference. // s3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(11, 9), // (15,9): warning CS8602: Possible dereference of a null reference. // s4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(15, 9), // (19,9): warning CS8602: Possible dereference of a null reference. // s5.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(19, 9) ); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitObjectInitializerReceiver() { var comp = CreateCompilation(@" public class B { public B? f2; public B? f3; } public class C { public B? f; static void Main() { new C() { f = { f2 = null, f3 = null }}; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,23): warning CS8602: Dereference of a possibly null reference. // new C() { f = { f2 = null, f3 = null }}; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "{ f2 = null, f3 = null }").WithLocation(12, 23) ); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitObjectInitializerReceiver_ReceiverNotNullable() { var comp = CreateCompilation(@" public class B { public B? f2; } public class C { public B f; static void Main() { new C() { f = { f2 = null }}; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8618: Non-nullable field 'f' is uninitialized. // public B f; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "f").WithArguments("field", "f").WithLocation(8, 14) ); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitObjectInitializerReceiver_ReceiverOblivious() { var comp = CreateCompilation(@" public class B { public B? f2; } public class C { #nullable disable public B f; #nullable enable static void Main() { new C() { f = { f2 = null }}; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitObjectInitializerReceiver_ReceiverNullableIndexer() { var comp = CreateCompilation(@" public class B { public B? f2; } public class C { static void Main() { new C() { [0] = { f2 = null }}; } public B? this[int i] { get => throw null!; set => throw null!; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,25): warning CS8602: Dereference of a possibly null reference. // new C() { [0] = { f2 = null }}; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "{ f2 = null }").WithLocation(10, 25) ); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitObjectInitializerReceiver_Nested() { var comp = CreateCompilation(@" public class B { public B? f2; } public class C { public C? fc; public B? fb; static void Main() { new C() { fc = { fb = { f2 = null} }}; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,24): warning CS8602: Dereference of a possibly null reference. // new C() { fc = { fb = { f2 = null} }}; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "{ fb = { f2 = null} }").WithLocation(12, 24), // (12,31): warning CS8602: Dereference of a possibly null reference. // new C() { fc = { fb = { f2 = null} }}; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "{ f2 = null}").WithLocation(12, 31) ); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitObjectInitializerReceiver_Index() { var comp = CreateCompilation(@" public class B { public B? this[int i] { get => throw null!; set => throw null!; } } public class C { public B? f; static void Main() { new C() { f = { [0] = null }}; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,23): warning CS8602: Dereference of a possibly null reference. // new C() { f = { [0] = null }}; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "{ [0] = null }").WithLocation(11, 23) ); } [Fact, WorkItem(32495, "https://github.com/dotnet/roslyn/issues/32495")] public void CheckImplicitCollectionInitializerReceiver() { var comp = CreateCompilation(@" public class B : System.Collections.Generic.IEnumerable { public void Add(int i) { } System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null!; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null!; } public class C { public B? f; static void Main() { new C() { f = { 1 }}; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,23): warning CS8602: Dereference of a possibly null reference. // new C() { f = { 1 }}; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "{ 1 }").WithLocation(13, 23) ); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_ReturnType() { var comp = CreateCompilation(@" using System.Collections.Generic; class C { static void M(object? o, object o2) { L(o)[0].ToString(); // 1 foreach (var x in L(o)) { x.ToString(); // 2 } L(o2)[0].ToString(); } static List L(T t) => null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // L(o)[0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "L(o)[0]").WithLocation(7, 9), // (10,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 13)); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_ReturnType_Inferred() { var comp = CreateCompilation(@" public class C { public T Field = default!; public C this[T index] { get => throw null!; set => throw null!; } } public class Main { static void M(object? o, object o2) { if (o is null) return; L(o)[0].Field.ToString(); o2 = null; L(o2)[0].Field.ToString(); // 1 } static C L(U u) => null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // o2 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 14), // (15,9): warning CS8602: Dereference of a possibly null reference. // L(o2)[0].Field.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "L(o2)[0].Field").WithLocation(15, 9) ); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_ReturnType_NestedNullability_Inferred() { var comp = CreateCompilation(@" public class C { public T this[int index] { get => throw null!; set => throw null!; } } public class Program { static void M(object? x) { var y = L(new[] { x }); y[0][0].ToString(); // warning if (x == null) return; var z = L(new[] { x }); z[0][0].ToString(); // ok } static C L(U u) => null!; } ", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // y[0][0].ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y[0][0]").WithLocation(11, 9) ); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_SetterArguments() { var comp = CreateCompilation(@" public class C { public int this[T index] { get => throw null!; set => throw null!; } } class Program { static void M(object? o, object o2) { L(o)[o] = 1; L(o)[o2] = 2; L(o2)[o] = 3; // warn L(o2)[o2] = 4; } static C L(U u) => null!; } ", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,15): warning CS8604: Possible null reference argument for parameter 'index' in 'int C.this[object index]'. // L(o2)[o] = 3; // warn Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("index", "int C.this[object index]").WithLocation(13, 15) ); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_SetterArguments_Inferred() { var comp = CreateCompilation(@" public class C { public int this[T index] { get => throw null!; set => throw null!; } } class Program { static void M(object? o, object o2, object? input, object input2) { if (o is null) return; L(o)[input] = 1; // 1 L(o)[input2] = 2; o2 = null; L(o2)[input] = 3; L(o2)[input2] = 4; } static C L(U u) => null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,14): warning CS8604: Possible null reference argument for parameter 'index' in 'int C.this[object index]'. // L(o)[input] = 1; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "input").WithArguments("index", "int C.this[object index]").WithLocation(11, 14), // (14,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // o2 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 14) ); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_GetterArguments() { var comp = CreateCompilation(@" public class C { public int this[T index] { get => throw null!; set => throw null!; } } class Program { static void M(object? o, object o2) { _ = L(o)[o]; _ = L(o)[o2]; _ = L(o2)[o]; // warn _ = L(o2)[o2]; } static C L(U u) => null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,19): warning CS8604: Possible null reference argument for parameter 'index' in 'int C.this[object index]'. // _ = L(o2)[o]; // warn Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("index", "int C.this[object index]").WithLocation(13, 19) ); } [Fact, WorkItem(29964, "https://github.com/dotnet/roslyn/issues/29964")] public void IndexerUpdatedBasedOnReceiver_SetterArguments_NestedNullability() { var comp = CreateCompilation(@" public class C { public int this[C index] { get => throw null!; set => throw null!; } } class Program { static void M(object? o, object o2) { L(o)[L(o)] = 1; L(o)[L(o2)] = 2; // 1 L(o2)[L(o)] = 3; // 2 L(o2)[L(o2)] = 4; } static C L(U u) => null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,14): warning CS8620: Argument of type 'C' cannot be used for parameter 'index' of type 'C' in 'int C.this[C index]' due to differences in the nullability of reference types. // L(o)[L(o2)] = 2; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "L(o2)").WithArguments("C", "C", "index", "int C.this[C index]").WithLocation(11, 14), // (13,15): warning CS8620: Argument of type 'C' cannot be used for parameter 'index' of type 'C' in 'int C.this[C index]' due to differences in the nullability of reference types. // L(o2)[L(o)] = 3; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "L(o)").WithArguments("C", "C", "index", "int C.this[C index]").WithLocation(13, 15) ); } [Fact, WorkItem(33289, "https://github.com/dotnet/roslyn/issues/33289")] public void ConditionalReceiver() { var comp = CreateCompilation(@" public class Container { public T Field = default!; } class C { static void M(string? s) { var x = Create(s); _ = x /*T:Container?*/; x?.Field.ToString(); // 1 } public static Container? Create(U u) => new Container(); }", options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (13,11): warning CS8602: Dereference of a possibly null reference. // x?.Field.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".Field").WithLocation(13, 11) ); } [Fact, WorkItem(28792, "https://github.com/dotnet/roslyn/issues/28792")] public void ConditionalReceiver_Verify28792() { var comp = CreateNullableCompilation(@" class C { void M(T t) => t?.ToString(); }"); comp.VerifyDiagnostics(); } [Fact, WorkItem(33289, "https://github.com/dotnet/roslyn/issues/33289")] public void ConditionalReceiver_Chained() { var comp = CreateCompilation(@" public class Container { public T Field = default!; } class C { static void M(string? s) { var x = Create(s); if (x is null) return; _ = x /*T:Container!*/; x?.Field.ToString(); // 1 x = Create(s); if (x is null) return; x.Field?.ToString(); } public static Container? Create(U u) => new Container(); }", options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (14,11): warning CS8602: Dereference of a possibly null reference. // x?.Field.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".Field").WithLocation(14, 11) ); } [Fact, WorkItem(33289, "https://github.com/dotnet/roslyn/issues/33289")] public void ConditionalReceiver_Chained_Inversed() { var comp = CreateCompilation(@" public class Container { public T Field = default!; } class C { static void M(string s) { var x = Create(s); _ = x /*T:Container?*/; x?.Field.ToString(); x = Create(s); x.Field?.ToString(); // 1 } public static Container? Create(U u) => new Container(); }", options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (16,9): warning CS8602: Dereference of a possibly null reference. // x.Field?.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(16, 9) ); } [Fact, WorkItem(33289, "https://github.com/dotnet/roslyn/issues/33289")] public void ConditionalReceiver_Nested() { var comp = CreateCompilation(@" public class Container { public T Field = default!; } class C { static void M(string? s1, string s2) { var x = Create(s1); var y = Create(s2); x?.Field /*1*/ .Extension(y?.Field.ToString()); } public static Container? Create(U u) => new Container(); } public static class Extensions { public static void Extension(this string s, object? o) => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (13,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.Extension(string s, object? o)'. // x?.Field /*1*/ Diagnostic(ErrorCode.WRN_NullReferenceArgument, ".Field").WithArguments("s", "void Extensions.Extension(string s, object? o)").WithLocation(13, 11) ); } [Fact, WorkItem(33289, "https://github.com/dotnet/roslyn/issues/33289")] public void ConditionalReceiver_MiscTypes() { var comp = CreateCompilation(@" public class Container { public T M() => default!; } class C { static void M(int i, Missing m, string s, T t) { Create(i)?.M().ToString(); Create(m)?.M().ToString(); Create(s)?.M().ToString(); Create(t)?.M().ToString(); // 1 } public static Container? Create(U u) => new Container(); }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,29): error CS0246: The type or namespace name 'Missing' could not be found (are you missing a using directive or an assembly reference?) // static void M(int i, Missing m, string s, T t) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Missing").WithArguments("Missing").WithLocation(8, 29), // (13,19): warning CS8602: Dereference of a possibly null reference. // Create(t)?.M().ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".M()").WithLocation(13, 19) ); } [Fact, WorkItem(26810, "https://github.com/dotnet/roslyn/issues/26810")] public void LockStatement() { var comp = CreateCompilation(@" class C { void F(object? maybeNull, object nonNull, Missing? annotatedMissing, Missing unannotatedMissing) { lock (maybeNull) { } lock (nonNull) { } lock (annotatedMissing) { } lock (unannotatedMissing) { } } #nullable disable void F(object oblivious, Missing obliviousMissing) #nullable enable { lock (oblivious) { } lock (obliviousMissing) { } } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,47): error CS0246: The type or namespace name 'Missing' could not be found (are you missing a using directive or an assembly reference?) // void F(object? maybeNull, object nonNull, Missing? annotatedMissing, Missing unannotatedMissing) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Missing").WithArguments("Missing").WithLocation(4, 47), // (4,74): error CS0246: The type or namespace name 'Missing' could not be found (are you missing a using directive or an assembly reference?) // void F(object? maybeNull, object nonNull, Missing? annotatedMissing, Missing unannotatedMissing) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Missing").WithArguments("Missing").WithLocation(4, 74), // (6,15): warning CS8602: Dereference of a possibly null reference. // lock (maybeNull) { } Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "maybeNull").WithLocation(6, 15), // (8,15): error CS0185: 'Missing?' is not a reference type as required by the lock statement // lock (annotatedMissing) { } Diagnostic(ErrorCode.ERR_LockNeedsReference, "annotatedMissing").WithArguments("Missing?").WithLocation(8, 15), // (12,30): error CS0246: The type or namespace name 'Missing' could not be found (are you missing a using directive or an assembly reference?) // void F(object oblivious, Missing obliviousMissing) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Missing").WithArguments("Missing").WithLocation(12, 30) ); } [Fact, WorkItem(33537, "https://github.com/dotnet/roslyn/issues/33537")] public void SuppressOnNullLiteralInAs() { var comp = CreateCompilation(@" class C { public static void Main() { var x = null! as object; } }"); comp.VerifyDiagnostics(); } [Fact, WorkItem(26654, "https://github.com/dotnet/roslyn/issues/26654")] [WorkItem(27522, "https://github.com/dotnet/roslyn/issues/27522")] public void SuppressNullableWarning_DeclarationExpression() { var source = @" public class C { public void M(out string? x) => throw null!; public void M2() { M(out string y!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // We don't allow suppressions on out-variable-declarations at this point (LDM 2/13/2019) comp.VerifyDiagnostics( // (7,23): error CS1003: Syntax error, ',' expected // M(out string y!); Diagnostic(ErrorCode.ERR_SyntaxError, "!").WithArguments(",", "!").WithLocation(7, 23), // (7,24): error CS1525: Invalid expression term ')' // M(out string y!); Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(7, 24) ); } [Fact, WorkItem(26654, "https://github.com/dotnet/roslyn/issues/26654")] public void SuppressNullableWarning_LocalDeclarationAndAssignmentTarget() { var source = @" public class C { public void M2() { object y! = null; object y2; y2! = null; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // We don't allow suppressions in those positions at this point (LDM 2/13/2019) comp.VerifyDiagnostics( // (6,16): warning CS0168: The variable 'y' is declared but never used // object y! = null; Diagnostic(ErrorCode.WRN_UnreferencedVar, "y").WithArguments("y").WithLocation(6, 16), // (6,17): error CS1002: ; expected // object y! = null; Diagnostic(ErrorCode.ERR_SemicolonExpected, "!").WithLocation(6, 17), // (6,19): error CS1525: Invalid expression term '=' // object y! = null; Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(6, 19), // (7,16): warning CS0219: The variable 'y2' is assigned but its value is never used // object y2; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y2").WithArguments("y2").WithLocation(7, 16), // (8,9): error CS8598: The suppression operator is not allowed in this context // y2! = null; Diagnostic(ErrorCode.ERR_IllegalSuppression, "y2").WithLocation(8, 9), // (8,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2! = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 15) ); } [Fact] [WorkItem(788968, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/788968")] public void MissingMethodOnTupleLiteral() { var source = @" #nullable enable class C { void M() { (0, (string?)null).Missing(); _ = (0, (string?)null).Missing; } } "; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (7,28): error CS1061: '(int, string)' does not contain a definition for 'Missing' and no accessible extension method 'Missing' accepting a first argument of type '(int, string)' could be found (are you missing a using directive or an assembly reference?) // (0, (string?)null).Missing(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Missing").WithArguments("(int, string)", "Missing").WithLocation(7, 28), // (8,32): error CS1061: '(int, string)' does not contain a definition for 'Missing' and no accessible extension method 'Missing' accepting a first argument of type '(int, string)' could be found (are you missing a using directive or an assembly reference?) // _ = (0, (string?)null).Missing; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Missing").WithArguments("(int, string)", "Missing").WithLocation(8, 32) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void SuppressNullableWarning_RefSpanReturn() { var comp = CreateCompilationWithMscorlibAndSpan(@" using System; class C { ref Span M(bool b) { Span x = stackalloc byte[10]; ref Span y = ref x!; if (b) return ref y; // 1 else return ref y!; // 2 } ref Span M2(ref Span x, bool b) { if (b) return ref x; // 3 else return ref x!; } }", options: WithNonNullTypes(TestOptions.ReleaseDll, NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (10,24): error CS8157: Cannot return 'y' by reference because it was initialized to a value that cannot be returned by reference // return ref y; // 1 Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "y").WithArguments("y").WithLocation(10, 24), // (12,24): error CS8157: Cannot return 'y' by reference because it was initialized to a value that cannot be returned by reference // return ref y!; // 2 Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "y").WithArguments("y").WithLocation(12, 24), // (17,24): warning CS8619: Nullability of reference types in value of type 'Span' doesn't match target type 'Span'. // return ref x; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("System.Span", "System.Span").WithLocation(17, 24) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void SuppressNullableWarning_RefReassignment() { var comp = CreateCompilation(@" class C { void M() { ref string x = ref NullableRef(); // 1 ref string x2 = ref x; // 2 ref string x3 = ref x!; ref string y = ref NullableRef()!; ref string y2 = ref y; ref string y3 = ref y!; } ref string? NullableRef() => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,28): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // ref string x = ref NullableRef(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "NullableRef()").WithArguments("string?", "string").WithLocation(6, 28), // (7,29): warning CS8601: Possible null reference assignment. // ref string x2 = ref x; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 29) ); } [Fact] public void SuppressNullableWarning_This() { var comp = CreateCompilation(@" class C { void M() { this!.M(); } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void SuppressNullableWarning_UnaryOperator() { var comp = CreateCompilation(@" class C { void M(C? y) { y++; y!++; y--; } public static C operator++(C x) => throw null!; public static C operator--(C? x) => throw null!; }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8604: Possible null reference argument for parameter 'x' in 'C C.operator ++(C x)'. // y++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "C C.operator ++(C x)").WithLocation(6, 9) ); } [Fact, WorkItem(30151, "https://github.com/dotnet/roslyn/issues/30151")] public void SuppressNullableWarning_WholeArrayInitializer() { var comp = CreateCompilationWithMscorlibAndSpan(@" class C { unsafe void M() { string[] s = new[] { null, string.Empty }; // expecting a warning string[] s2 = (new[] { null, string.Empty })!; int* s3 = (stackalloc[] { 1 })!; System.Span s4 = (stackalloc[] { null, string.Empty })!; } }", options: TestOptions.UnsafeDebugDll); // Missing warning // Need to confirm whether this suppression should be allowed or be effective // If so, we need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/30151 comp.VerifyDiagnostics( // (8,20): error CS8346: Conversion of a stackalloc expression of type 'int' to type 'int*' is not possible. // int* s3 = (stackalloc[] { 1 })!; Diagnostic(ErrorCode.ERR_StackAllocConversionNotPossible, "stackalloc[] { 1 }").WithArguments("int", "int*").WithLocation(8, 20), // (9,35): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('string') // System.Span s4 = (stackalloc[] { null, string.Empty })!; Diagnostic(ErrorCode.ERR_ManagedAddr, "stackalloc[] { null, string.Empty }").WithArguments("string").WithLocation(9, 35)); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_NullCoalescingAssignment() { var comp = CreateCompilation(@" class C { void M(int? i, int i2, dynamic d) { i! ??= i2; // 1 i ??= i2!; i! ??= d; // 2 i ??= d!; } void M(string? s, string s2, dynamic d) { s! ??= s2; // 3 s ??= s2!; s! ??= d; // 4 s ??= d!; } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): error CS8598: The suppression operator is not allowed in this context // i! ??= i2; // 1 Diagnostic(ErrorCode.ERR_IllegalSuppression, "i").WithLocation(6, 9), // (8,9): error CS8598: The suppression operator is not allowed in this context // i! ??= d; // 2 Diagnostic(ErrorCode.ERR_IllegalSuppression, "i").WithLocation(8, 9), // (13,9): error CS8598: The suppression operator is not allowed in this context // s! ??= s2; // 3 Diagnostic(ErrorCode.ERR_IllegalSuppression, "s").WithLocation(13, 9), // (15,9): error CS8598: The suppression operator is not allowed in this context // s! ??= d; // 4 Diagnostic(ErrorCode.ERR_IllegalSuppression, "s").WithLocation(15, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_ExpressionTree() { var comp = CreateCompilation(@" using System; using System.Linq.Expressions; class C { void M() { string x = null; Expression> e = () => x!; Expression> e2 = (() => x)!; Expression>> e3 = () => M2!; } string M2() => throw null!; }"); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_QueryReceiver() { string source = @" using System; namespace NS { } static class C { static void Main() { _ = from x in null! select x; _ = from x in default! select x; _ = from x in (y => y)! select x; _ = from x in NS! select x; _ = from x in Main! select x; } static object Select(this object x, Func y) { return null; } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,29): error CS0186: Use of null is not valid in this context // _ = from x in null! select x; Diagnostic(ErrorCode.ERR_NullNotValid, "select x").WithLocation(8, 29), // (9,32): error CS8312: Use of default literal is not valid in this context // _ = from x in default! select x; Diagnostic(ErrorCode.ERR_DefaultLiteralNotValid, "select x").WithLocation(9, 32), // (10,33): error CS1936: Could not find an implementation of the query pattern for source type 'anonymous method'. 'Select' not found. // _ = from x in (y => y)! select x; Diagnostic(ErrorCode.ERR_QueryNoProvider, "select x").WithArguments("anonymous method", "Select").WithLocation(10, 33), // (11,23): error CS8598: The suppression operator is not allowed in this context // _ = from x in NS! select x; Diagnostic(ErrorCode.ERR_IllegalSuppression, "NS").WithLocation(11, 23), // (11,23): error CS0119: 'NS' is a namespace, which is not valid in the given context // _ = from x in NS! select x; Diagnostic(ErrorCode.ERR_BadSKunknown, "NS").WithArguments("NS", "namespace").WithLocation(11, 23), // (12,23): error CS0119: 'C.Main()' is a method, which is not valid in the given context // _ = from x in Main! select x; Diagnostic(ErrorCode.ERR_BadSKunknown, "Main").WithArguments("C.Main()", "method").WithLocation(12, 23) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Query() { string source = @" using System.Linq; class C { static void M(System.Collections.Generic.IEnumerable c) { var q = (from x in c select x)!; } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_EventInCompoundAssignment() { var comp = CreateCompilation(@" class C { public event System.Action E; void M() { E! += () => {}; E(); } }"); comp.VerifyDiagnostics( // (7,9): error CS8598: The suppression operator is not allowed in this context // E! += () => {}; Diagnostic(ErrorCode.ERR_IllegalSuppression, "E").WithLocation(7, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void OperationsInNonDeclaringType() { var text = @" class C { public event System.Action E; } class D { void Method(ref System.Action a, C c) { c.E! = a; //CS0070 c.E! += a; a = c.E!; //CS0070 Method(ref c.E!, c); //CS0070 c.E!.Invoke(); //CS0070 bool b1 = c.E! is System.Action; //CS0070 c.E!++; //CS0070 c.E! |= true; //CS0070 } } "; CreateCompilation(text).VerifyDiagnostics( // (11,11): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // c.E! = a; //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(11, 11), // (12,9): error CS8598: The suppression operator is not allowed in this context // c.E! += a; Diagnostic(ErrorCode.ERR_IllegalSuppression, "c.E").WithLocation(12, 9), // (13,15): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // a = c.E!; //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(13, 15), // (14,22): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // Method(ref c.E!, c); //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(14, 22), // (15,11): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // c.E!.Invoke(); //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(15, 11), // (16,21): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // bool b1 = c.E! is System.Action; //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(16, 21), // (17,11): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // c.E!++; //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(17, 11), // (18,9): error CS8598: The suppression operator is not allowed in this context // c.E! |= true; //CS0070 Diagnostic(ErrorCode.ERR_IllegalSuppression, "c.E").WithLocation(18, 9), // (18,11): error CS0070: The event 'C.E' can only appear on the left hand side of += or -= (except when used from within the type 'C') // c.E! |= true; //CS0070 Diagnostic(ErrorCode.ERR_BadEventUsage, "E").WithArguments("C.E", "C").WithLocation(18, 11) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Fixed() { var text = @" public class MyClass { int field = 0; unsafe public void Main() { int i = 45; fixed (int *j = &(i!)) { } fixed (int *k = &(this!.field)) { } int[] a = new int[] {1,2,3}; fixed (int *b = a!) { fixed (int *c = b!) { } } } } "; CreateCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (8,25): error CS0213: You cannot use the fixed statement to take the address of an already fixed expression // fixed (int *j = &(i!)) { } Diagnostic(ErrorCode.ERR_FixedNotNeeded, "&(i!)").WithLocation(8, 25), // (8,27): error CS8598: The suppression operator is not allowed in this context // fixed (int *j = &(i!)) { } Diagnostic(ErrorCode.ERR_IllegalSuppression, "i").WithLocation(8, 27), // (14,29): error CS8385: The given expression cannot be used in a fixed statement // fixed (int *c = b!) { } Diagnostic(ErrorCode.ERR_ExprCannotBeFixed, "b").WithLocation(14, 29) ); } [Fact, WorkItem(31748, "https://github.com/dotnet/roslyn/issues/31748")] public void NullableRangeIndexer() { var text = @" #nullable enable class Program { void M(int[] x, string m) { var y = x[1..3]; var z = m[1..3]; } }" + TestSources.GetSubArray; CreateCompilationWithIndexAndRange(text).VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MemberAccess() { var comp = CreateCompilation(@" namespace NS { public static class C { public static void M() { _ = null!.field; // 1 _ = default!.field; // 2 _ = NS!.C.field; // 3 _ = NS.C!.field; // 4 _ = nameof(C!.M); // 5 _ = nameof(C.M!); // 6 _ = nameof(missing!); // 7 } } public class Base { public virtual void M() { } } public class D : Base { public override void M() { _ = this!.ToString(); // 8 _ = base!.ToString(); // 9 } } }"); // Like cast, suppressions are allowed on `this`, but not on `base` comp.VerifyDiagnostics( // (8,17): error CS0023: Operator '.' cannot be applied to operand of type '' // _ = null!.field; // 1 Diagnostic(ErrorCode.ERR_BadUnaryOp, "null!.field").WithArguments(".", "").WithLocation(8, 17), // (9,25): error CS0023: Operator '.' cannot be applied to operand of type 'default' // _ = default!.field; // 2 Diagnostic(ErrorCode.ERR_BadUnaryOp, ".").WithArguments(".", "default").WithLocation(9, 25), // (10,17): error CS8598: The suppression operator is not allowed in this context // _ = NS!.C.field; // 3 Diagnostic(ErrorCode.ERR_IllegalSuppression, "NS").WithLocation(10, 17), // (10,23): error CS0117: 'C' does not contain a definition for 'field' // _ = NS!.C.field; // 3 Diagnostic(ErrorCode.ERR_NoSuchMember, "field").WithArguments("NS.C", "field").WithLocation(10, 23), // (11,17): error CS8598: The suppression operator is not allowed in this context // _ = NS.C!.field; // 4 Diagnostic(ErrorCode.ERR_IllegalSuppression, "NS.C").WithLocation(11, 17), // (11,23): error CS0117: 'C' does not contain a definition for 'field' // _ = NS.C!.field; // 4 Diagnostic(ErrorCode.ERR_NoSuchMember, "field").WithArguments("NS.C", "field").WithLocation(11, 23), // (12,24): error CS8598: The suppression operator is not allowed in this context // _ = nameof(C!.M); // 5 Diagnostic(ErrorCode.ERR_IllegalSuppression, "C").WithLocation(12, 24), // (12,24): error CS8082: Sub-expression cannot be used in an argument to nameof. // _ = nameof(C!.M); // 5 Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "C!").WithLocation(12, 24), // (13,24): error CS8081: Expression does not have a name. // _ = nameof(C.M!); // 6 Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "C.M!").WithLocation(13, 24), // (14,24): error CS0103: The name 'missing' does not exist in the current context // _ = nameof(missing!); // 7 Diagnostic(ErrorCode.ERR_NameNotInContext, "missing").WithArguments("missing").WithLocation(14, 24), // (23,17): error CS0175: Use of keyword 'base' is not valid in this context // _ = base!.ToString(); // 9 Diagnostic(ErrorCode.ERR_BaseIllegal, "base").WithLocation(23, 17) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SymbolInfoForMethodGroup03() { var source = @" public class A { public static void M(A a) { _ = nameof(a.Extension!); } } public static class X1 { public static string Extension(this A a) { return null; } }"; var compilation = CreateCompilationWithMscorlib40AndSystemCore(source); compilation.VerifyDiagnostics( // (6,20): error CS8081: Expression does not have a name. // _ = nameof(a.Extension!); Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "a.Extension!").WithLocation(6, 20) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_StringInterpolation() { var source = @" public class C { public static void Main() { M(""world"", null); } public static void M(string x, string? y) { System.IFormattable z = $""hello ""!; System.IFormattable z2 = $""{x} {y} {y!}""!; System.Console.Write(z); System.Console.Write(z2); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "hello world"); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var suppression = tree.GetRoot().DescendantNodes().OfType().First(); Assert.Equal(@"$""hello ""!", suppression.ToString()); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 // should be IFormattable twice //VerifyTypeInfo(model, suppression, "System.String", "System.IFormattable"); var interpolated = suppression.Operand; Assert.Equal(@"$""hello """, interpolated.ToString()); VerifyTypeInfo(model, interpolated, "System.String", "System.IFormattable"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_StringInterpolation_ExplicitCast() { var source = @" public class C { public static void Main() { M(""world"", null); } public static void M(string x, string? y) { var z = (System.IFormattable)($""hello ""!); var z2 = (System.IFormattable)($""{x} {y} {y!}""!); System.Console.Write(z); System.Console.Write(z2); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "hello world"); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 var suppression = tree.GetRoot().DescendantNodes().OfType().First(); Assert.Equal(@"$""hello ""!", suppression.ToString()); //VerifyTypeInfo(model, suppression, "System.String", "System.String"); var interpolated = suppression.Operand; Assert.Equal(@"$""hello """, interpolated.ToString()); VerifyTypeInfo(model, interpolated, "System.String", "System.String"); } private static void VerifyTypeInfo(SemanticModel model, ExpressionSyntax expression, string expectedType, string expectedConvertedType) { var type = model.GetTypeInfo(expression); if (expectedType is null) { Assert.Null(type.Type); } else { var actualType = type.Type.ToTestDisplayString(); Assert.True(expectedType == actualType, $"Unexpected TypeInfo.Type '{actualType}'"); } if (expectedConvertedType is null) { Assert.Null(type.ConvertedType); } else { var actualConvertedType = type.ConvertedType.ToTestDisplayString(); Assert.True(expectedConvertedType == actualConvertedType, $"Unexpected TypeInfo.ConvertedType '{actualConvertedType}'"); } } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Default() { var source = @"class C { static void M() { string s = default!; s.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); CompileAndVerify(comp); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var suppression = tree.GetRoot().DescendantNodes().OfType().Single(); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 //VerifyTypeInfo(model, suppression, "System.String", "System.String"); var literal = suppression.Operand; VerifyTypeInfo(model, literal, "System.String", "System.String"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Constant() { var source = @"class C { static void M() { const int i = 3!; _ = i; const string s = null!; _ = s; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var suppressions = tree.GetRoot().DescendantNodes().OfType().ToArray(); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 //Assert.Equal(3, model.GetConstantValue(suppressions[0]).Value); //Assert.Null(model.GetConstantValue(suppressions[1]).Value); } [Fact] public void SuppressNullableWarning_GetTypeInfo() { var source = @"class C { void M(string s, string? s2, C c, C c2) { _ = s!; _ = s2!; _ = c!; _ = c2!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var suppressions = tree.GetRoot().DescendantNodes().OfType().ToArray(); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 var s = model.GetTypeInfo(suppressions[0]); Assert.Equal("System.String", s.Type.ToTestDisplayString()); Assert.Equal("System.String", s.ConvertedType.ToTestDisplayString()); Assert.Equal("System.String s", model.GetSymbolInfo(suppressions[0]).Symbol.ToTestDisplayString()); var s2 = model.GetTypeInfo(suppressions[1]); Assert.Equal("System.String", s2.Type.ToTestDisplayString()); Assert.Equal("System.String", s2.ConvertedType.ToTestDisplayString()); Assert.Equal("System.String? s2", model.GetSymbolInfo(suppressions[1]).Symbol.ToTestDisplayString()); var c = model.GetTypeInfo(suppressions[2]); Assert.Equal("C", c.Type.ToTestDisplayString()); Assert.Equal("C", c.ConvertedType.ToTestDisplayString()); Assert.Equal("C c", model.GetSymbolInfo(suppressions[2]).Symbol.ToTestDisplayString()); var c2 = model.GetTypeInfo(suppressions[3]); Assert.Equal("C", c2.Type.ToTestDisplayString()); Assert.Equal("C", c2.ConvertedType.ToTestDisplayString()); Assert.Equal("C c2", model.GetSymbolInfo(suppressions[3]).Symbol.ToTestDisplayString()); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MethodGroupInNameof() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void M() { _ = nameof(C.M!); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,24): error CS0119: 'T' is a type, which is not valid in the given context // _ = nameof(C.M!); Diagnostic(ErrorCode.ERR_BadSKunknown, "T").WithArguments("T", "type").WithLocation(6, 24), // (6,27): error CS1525: Invalid expression term ')' // _ = nameof(C.M!); Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(6, 27) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MethodGroup() { var source = @"class C { delegate string Copier(string s); static void Main() { Copier c = M2; Copier c2 = M2!; } static string? M2(string? s) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (6,20): warning CS8621: Nullability of reference types in return type of 'string? C.M2(string? s)' doesn't match the target delegate 'C.Copier'. // Copier c = M2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M2").WithArguments("string? C.M2(string? s)", "C.Copier").WithLocation(6, 20) ); CompileAndVerify(comp); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 // unepxected answer from semantic model var suppression = tree.GetRoot().DescendantNodes().OfType().First(); Assert.Equal("M2!", suppression.ToString()); //VerifyTypeInfo(model, suppression, null, "C.Copier"); var methodGroup = suppression.Operand; VerifyTypeInfo(model, methodGroup, null, "C.Copier"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void InvalidUseOfMethodGroup() { var source = @"class A { internal object E() { return null; } private object F() { return null; } static void M(A a) { object o; a.E! += a.E!; // 1 if (a.E! != null) // 2 { M(a.E!); // 3 a.E!.ToString(); // 4 a.P!.ToString(); // 5 o = !(a.E!); // 6 o = a.E! ?? a.F!; // 7 } a.F! += a.F!; // 8 if (a.F! != null) // 9 { M(a.F!); // 10 a.F!.ToString(); // 11 o = !(a.F!); // 12 o = (o != null) ? a.E! : a.F!; // 13 } } }"; CreateCompilation(source).VerifyDiagnostics( // (8,9): error CS1656: Cannot assign to 'E' because it is a 'method group' // a.E! += a.E!; // 1 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "a.E").WithArguments("E", "method group").WithLocation(8, 9), // (9,13): error CS0019: Operator '!=' cannot be applied to operands of type 'method group' and '' // if (a.E! != null) // 2 Diagnostic(ErrorCode.ERR_BadBinaryOps, "a.E! != null").WithArguments("!=", "method group", "").WithLocation(9, 13), // (11,15): error CS1503: Argument 1: cannot convert from 'method group' to 'A' // M(a.E!); // 3 Diagnostic(ErrorCode.ERR_BadArgType, "a.E").WithArguments("1", "method group", "A").WithLocation(11, 15), // (12,15): error CS0119: 'A.E()' is a method, which is not valid in the given context // a.E!.ToString(); // 4 Diagnostic(ErrorCode.ERR_BadSKunknown, "E").WithArguments("A.E()", "method").WithLocation(12, 15), // (13,15): error CS1061: 'A' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?) // a.P!.ToString(); // 5 Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("A", "P").WithLocation(13, 15), // (14,17): error CS0023: Operator '!' cannot be applied to operand of type 'method group' // o = !(a.E!); // 6 Diagnostic(ErrorCode.ERR_BadUnaryOp, "!(a.E!)").WithArguments("!", "method group").WithLocation(14, 17), // (15,17): error CS0019: Operator '??' cannot be applied to operands of type 'method group' and 'method group' // o = a.E! ?? a.F!; // 7 Diagnostic(ErrorCode.ERR_BadBinaryOps, "a.E! ?? a.F!").WithArguments("??", "method group", "method group").WithLocation(15, 17), // (17,9): error CS1656: Cannot assign to 'F' because it is a 'method group' // a.F! += a.F!; // 8 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "a.F").WithArguments("F", "method group").WithLocation(17, 9), // (18,13): error CS0019: Operator '!=' cannot be applied to operands of type 'method group' and '' // if (a.F! != null) // 9 Diagnostic(ErrorCode.ERR_BadBinaryOps, "a.F! != null").WithArguments("!=", "method group", "").WithLocation(18, 13), // (20,15): error CS1503: Argument 1: cannot convert from 'method group' to 'A' // M(a.F!); // 10 Diagnostic(ErrorCode.ERR_BadArgType, "a.F").WithArguments("1", "method group", "A").WithLocation(20, 15), // (21,15): error CS0119: 'A.F()' is a method, which is not valid in the given context // a.F!.ToString(); // 11 Diagnostic(ErrorCode.ERR_BadSKunknown, "F").WithArguments("A.F()", "method").WithLocation(21, 15), // (22,17): error CS0023: Operator '!' cannot be applied to operand of type 'method group' // o = !(a.F!); // 12 Diagnostic(ErrorCode.ERR_BadUnaryOp, "!(a.F!)").WithArguments("!", "method group").WithLocation(22, 17), // (23,17): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'method group' and 'method group' // o = (o != null) ? a.E! : a.F!; // 13 Diagnostic(ErrorCode.ERR_InvalidQM, "(o != null) ? a.E! : a.F!").WithArguments("method group", "method group").WithLocation(23, 17) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_AccessPropertyWithoutArguments() { string source1 = @" Imports System Imports System.Runtime.InteropServices Public Interface IB Property Value(Optional index As Object = Nothing) As Object End Interface "; var reference = BasicCompilationUtils.CompileToMetadata(source1); string source2 = @" class CIB : IB { public dynamic get_Value(object index = null) { return ""Test""; } public void set_Value(object index = null, object Value = null) { } } class Test { static void Main() { IB x = new CIB(); System.Console.WriteLine(x.Value!.Length); } } "; var compilation2 = CreateCompilation(source2, new[] { reference.WithEmbedInteropTypes(true), CSharpRef }, options: TestOptions.ReleaseExe); CompileAndVerify(compilation2, expectedOutput: @"4"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_CollectionInitializerProperty() { var source = @" public class C { public string P { get; set; } = null!; void M() { _ = new C() { P! = null }; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,21): error CS1922: Cannot initialize type 'C' with a collection initializer because it does not implement 'System.Collections.IEnumerable' // _ = new C() { P! = null }; Diagnostic(ErrorCode.ERR_CollectionInitRequiresIEnumerable, "{ P! = null }").WithArguments("C").WithLocation(7, 21), // (7,23): error CS0747: Invalid initializer member declarator // _ = new C() { P! = null }; Diagnostic(ErrorCode.ERR_InvalidInitializerElementInitializer, "P! = null").WithLocation(7, 23), // (7,23): error CS8598: The suppression operator is not allowed in this context // _ = new C() { P! = null }; Diagnostic(ErrorCode.ERR_IllegalSuppression, "P").WithLocation(7, 23), // (7,28): warning CS8625: Cannot convert null literal to non-nullable reference type. // _ = new C() { P! = null }; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 28) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_InInvocation() { var source = @" public class C { public System.Action? field = null; void M() { this.M!(); nameof!(M); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): error CS8598: The suppression operator is not allowed in this context // this.M!(); Diagnostic(ErrorCode.ERR_IllegalSuppression, "this.M").WithLocation(7, 9), // (8,9): error CS0103: The name 'nameof' does not exist in the current context // nameof!(M); Diagnostic(ErrorCode.ERR_NameNotInContext, "nameof").WithArguments("nameof").WithLocation(8, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_InInvocation2() { var source = @" public class C { public System.Action? field = null; void M() { this!.field!(); } }"; var comp = CreateCompilationWithCSharp(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); CompileAndVerify(comp); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_InInvocationAndDynamic() { var source = @" public class C { void M() { dynamic? d = new object(); d.M!(); // 1 int z = d.y.z; d = null; d!.M(); d = null; int y = d.y; // 2 d = null; d.M!(); // 3 d += null; d += null!; } }"; // What warnings should we produce on dynamic? // Should `!` be allowed on members/invocations on dynamic? // See https://github.com/dotnet/roslyn/issues/32364 var comp = CreateCompilationWithCSharp(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): error CS8598: The suppression operator is not allowed in this context // d.M!(); // 1 Diagnostic(ErrorCode.ERR_IllegalSuppression, "d.M").WithLocation(7, 9), // (14,17): warning CS8602: Dereference of a possibly null reference. // int y = d.y; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d").WithLocation(14, 17), // (17,9): error CS8598: The suppression operator is not allowed in this context // d.M!(); // 3 Diagnostic(ErrorCode.ERR_IllegalSuppression, "d.M").WithLocation(17, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // d.M!(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d").WithLocation(17, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Stackalloc() { var comp = CreateCompilationWithMscorlibAndSpan(@" class Test { void M() { System.Span a3 = stackalloc[] { 1, 2, 3 }!; var x3 = true ? stackalloc[] { 1, 2, 3 }! : a3; } }", TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MethodGroup2() { var source = @"class C { delegate string? Copier(string? s); static void Main() { Copier c = M2; Copier c2 = M2!; } static string M2(string s) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (6,20): warning CS8622: Nullability of reference types in type of parameter 's' of 'string C.M2(string s)' doesn't match the target delegate 'C.Copier'. // Copier c = M2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M2").WithArguments("s", "string C.M2(string s)", "C.Copier").WithLocation(6, 20) ); CompileAndVerify(comp); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Lambda() { var source = @"class C { delegate string Copier(string s); static void Main() { Copier c = (string? x) => { return null; }!; Copier c2 = (string? x) => { return null; }; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (6,44): warning CS8603: Possible null reference return. // Copier c = (string? x) => { return null; }!; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 44), // (7,21): warning CS8622: Nullability of reference types in type of parameter 'x' of 'lambda expression' doesn't match the target delegate 'C.Copier'. // Copier c2 = (string? x) => { return null; }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(string? x) => { return null; }").WithArguments("x", "lambda expression", "C.Copier").WithLocation(7, 21), // (7,45): warning CS8603: Possible null reference return. // Copier c2 = (string? x) => { return null; }; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(7, 45) ); CompileAndVerify(comp); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var suppression = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("(string? x) => { return null; }!", suppression.ToString()); //VerifyTypeInfo(model, suppression, null, "C.Copier"); var lambda = suppression.Operand; Assert.Equal("(string? x) => { return null; }", lambda.ToString()); VerifyTypeInfo(model, lambda, null, "C.Copier"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Lambda_ExplicitCast() { var source = @"class C { delegate string Copier(string s); static void M() { var c = (Copier)((string? x) => { return null; }!); var c2 = (Copier)((string? x) => { return null; }); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,50): warning CS8603: Possible null reference return. // var c = (Copier)((string? x) => { return null; }!); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 50), // (7,18): warning CS8622: Nullability of reference types in type of parameter 'x' of 'lambda expression' doesn't match the target delegate 'C.Copier'. // var c2 = (Copier)((string? x) => { return null; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(Copier)((string? x) => { return null; })").WithArguments("x", "lambda expression", "C.Copier").WithLocation(7, 18), // (7,51): warning CS8603: Possible null reference return. // var c2 = (Copier)((string? x) => { return null; }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(7, 51) ); CompileAndVerify(comp); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 var suppression = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("(string? x) => { return null; }!", suppression.ToString()); //VerifyTypeInfo(model, suppression, "C.Copier", "C.Copier"); var lambda = suppression.Operand; Assert.Equal("(string? x) => { return null; }", lambda.ToString()); VerifyTypeInfo(model, lambda, null, "C.Copier"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Lambda2() { var source = @"class C { delegate string? Copier(string? s); static void Main() { Copier c = (string x) => { return string.Empty; }!; Copier c2 = (string x) => { return string.Empty; }; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (7,21): warning CS8622: Nullability of reference types in type of parameter 'x' of 'lambda expression' doesn't match the target delegate 'C.Copier'. // Copier c2 = (string x) => { return string.Empty; }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(string x) => { return string.Empty; }").WithArguments("x", "lambda expression", "C.Copier").WithLocation(7, 21) ); CompileAndVerify(comp); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var suppression = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("(string x) => { return string.Empty; }!", suppression.ToString()); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 //VerifyTypeInfo(model, suppression, null, "C.Copier"); var lambda = suppression.Operand; Assert.Equal("(string x) => { return string.Empty; }", lambda.ToString()); VerifyTypeInfo(model, lambda, null, "C.Copier"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Lambda2_ExplicitCast() { var source = @"class C { delegate string? Copier(string? s); static void Main() { var c = (Copier)((string x) => { return string.Empty; }!); var c2 = (Copier)((string x) => { return string.Empty; }); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (7,18): warning CS8622: Nullability of reference types in type of parameter 'x' of 'lambda expression' doesn't match the target delegate 'C.Copier'. // var c2 = (Copier)((string x) => { return string.Empty; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(Copier)((string x) => { return string.Empty; })").WithArguments("x", "lambda expression", "C.Copier").WithLocation(7, 18) ); CompileAndVerify(comp); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 var suppression = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("(string x) => { return string.Empty; }!", suppression.ToString()); //VerifyTypeInfo(model, suppression, "C.Copier", "C.Copier"); var lambda = suppression.Operand; Assert.Equal("(string x) => { return string.Empty; }", lambda.ToString()); VerifyTypeInfo(model, lambda, null, "C.Copier"); } [Fact, WorkItem(32697, "https://github.com/dotnet/roslyn/issues/32697")] public void SuppressNullableWarning_LambdaInOverloadResolution() { var source = @"class C { static void Main(string? x) { var s = M(() => { return x; }); s /*T:string?*/ .ToString(); // 1 var s2 = M(() => { return x; }!); // suppressed s2 /*T:string?*/ .ToString(); // 2 var s3 = M(M2); s3 /*T:string?*/ .ToString(); // 3 var s4 = M(M2!); // suppressed s4 /*T:string?*/ .ToString(); // 4 } static T M(System.Func x) => throw null!; static string? M2() => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s /*T:string?*/ .ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // s2 /*T:string?*/ .ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(9, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // s3 /*T:string?*/ .ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(12, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // s4 /*T:string?*/ .ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(15, 9)); CompileAndVerify(comp); } [Fact, WorkItem(32698, "https://github.com/dotnet/roslyn/issues/32698")] public void SuppressNullableWarning_DelegateCreation() { var source = @"class C { static void Main() { _ = new System.Func((string? x) => { return null; }!); _ = new System.Func((string x) => { return string.Empty; }!); _ = new System.Func(M1!); _ = new System.Func(M2!); // without suppression _ = new System.Func((string? x) => { return null; }); // 1 _ = new System.Func((string x) => { return string.Empty; }); // 2 _ = new System.Func(M1); // 3 _ = new System.Func(M2); // 4 } static string? M1(string? x) => throw null!; static string M2(string x) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (5,69): warning CS8603: Possible null reference return. // _ = new System.Func((string? x) => { return null; }!); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(5, 69), // (11,57): warning CS8622: Nullability of reference types in type of parameter 'x' of 'lambda expression' doesn't match the target delegate 'Func'. // _ = new System.Func((string? x) => { return null; }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("x", "lambda expression", "System.Func").WithLocation(11, 57), // (11,69): warning CS8603: Possible null reference return. // _ = new System.Func((string? x) => { return null; }); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(11, 69), // (12,58): warning CS8622: Nullability of reference types in type of parameter 'x' of 'lambda expression' doesn't match the target delegate 'Func'. // _ = new System.Func((string x) => { return string.Empty; }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("x", "lambda expression", "System.Func").WithLocation(12, 58), // (13,45): warning CS8621: Nullability of reference types in return type of 'string? C.M1(string? x)' doesn't match the target delegate 'Func'. // _ = new System.Func(M1); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M1").WithArguments("string? C.M1(string? x)", "System.Func").WithLocation(13, 45), // (14,47): warning CS8622: Nullability of reference types in type of parameter 'x' of 'string C.M2(string x)' doesn't match the target delegate 'Func'. // _ = new System.Func(M2); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M2").WithArguments("x", "string C.M2(string x)", "System.Func").WithLocation(14, 47)); CompileAndVerify(comp); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MethodGroupInOverloadResolution_NoReceiver() { var source = @"using System; using System.Collections.Generic; class A { class B { void F() { IEnumerable c = null!; c.S(G); c.S(G!); IEnumerable c2 = null!; c2.S(G); c2.S(G2); } } object G(string s) => throw null!; object G2(string? s) => throw null!; } static class E { internal static IEnumerable S(this IEnumerable c, Func f) { throw new NotImplementedException(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,17): error CS0120: An object reference is required for the non-static field, method, or property 'A.G(string)' // c.S(G); Diagnostic(ErrorCode.ERR_ObjectRequired, "G").WithArguments("A.G(string)").WithLocation(10, 17), // (11,17): error CS0120: An object reference is required for the non-static field, method, or property 'A.G(string)' // c.S(G!); Diagnostic(ErrorCode.ERR_ObjectRequired, "G").WithArguments("A.G(string)").WithLocation(11, 17), // (14,18): error CS0120: An object reference is required for the non-static field, method, or property 'A.G(string)' // c2.S(G); Diagnostic(ErrorCode.ERR_ObjectRequired, "G").WithArguments("A.G(string)").WithLocation(14, 18), // (15,18): error CS0120: An object reference is required for the non-static field, method, or property 'A.G2(string?)' // c2.S(G2); Diagnostic(ErrorCode.ERR_ObjectRequired, "G2").WithArguments("A.G2(string?)").WithLocation(15, 18) ); } [Fact] [WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] [WorkItem(33635, "https://github.com/dotnet/roslyn/issues/33635")] public void SuppressNullableWarning_MethodGroupInOverloadResolution() { var source = @"using System; using System.Collections.Generic; class A { void M() { IEnumerable c = null!; c.S(G)/*T:System.Collections.Generic.IEnumerable!*/; // 1 c.S(G!)/*T:System.Collections.Generic.IEnumerable!*/; IEnumerable c2 = null!; c2.S(G)/*T:System.Collections.Generic.IEnumerable!*/; c2.S(G2)/*T:System.Collections.Generic.IEnumerable!*/; } static object G(string s) => throw null!; static object G2(string? s) => throw null!; } static class E { internal static IEnumerable S(this IEnumerable c, Func f) { throw new NotImplementedException(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8622: Nullability of reference types in type of parameter 's' of 'object A.G(string s)' doesn't match the target delegate 'Func'. // c.S(G)/*T:IEnumerable!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "G").WithArguments("s", "object A.G(string s)", "System.Func").WithLocation(8, 13) ); comp.VerifyTypes(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void ErrorInLambdaArgumentList() { var source = @" class Program { public Program(string x) : this((() => x)!) { } }"; CreateCompilation(source).VerifyDiagnostics( // (4,38): error CS1660: Cannot convert lambda expression to type 'string' because it is not a delegate type // public Program(string x) : this((() => x)!) { } Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => x").WithArguments("lambda expression", "string").WithLocation(4, 38) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void CS1113ERR_ValueTypeExtDelegate01() { var source = @"class C { public void M() { } } interface I { void M(); } enum E { } struct S { public void M() { } } static class SC { static void Test(C c, I i, E e, S s, double d) { System.Action cm = c.M!; // OK -- instance method System.Action cm1 = c.M1!; // OK -- extension method on ref type System.Action im = i.M!; // OK -- instance method System.Action im2 = i.M2!; // OK -- extension method on ref type System.Action em3 = e.M3!; // BAD -- extension method on value type System.Action sm = s.M!; // OK -- instance method System.Action sm4 = s.M4!; // BAD -- extension method on value type System.Action dm5 = d.M5!; // BAD -- extension method on value type } static void M1(this C c) { } static void M2(this I i) { } static void M3(this E e) { } static void M4(this S s) { } static void M5(this double d) { } }"; CreateCompilationWithMscorlib40(source, references: new[] { SystemCoreRef }).VerifyDiagnostics( // (24,29): error CS1113: Extension methods 'SC.M3(E)' defined on value type 'E' cannot be used to create delegates Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "e.M3").WithArguments("SC.M3(E)", "E").WithLocation(24, 29), // (26,29): error CS1113: Extension methods 'SC.M4(S)' defined on value type 'S' cannot be used to create delegates Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "s.M4").WithArguments("SC.M4(S)", "S").WithLocation(26, 29), // (27,29): error CS1113: Extension methods 'SC.M5(double)' defined on value type 'double' cannot be used to create delegates Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "d.M5").WithArguments("SC.M5(double)", "double").WithLocation(27, 29)); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void BugCodePlex_30_01() { string source1 = @" using System; class C { static void Main() { Goo(() => { return () => 0; ; }!); Goo(() => { return () => 0; }!); } static void Goo(Func> x) { Console.Write(1); } static void Goo(Func> x) { Console.Write(2); } } "; CompileAndVerify(source1, expectedOutput: @"22"); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_AddressOfWithLambdaOrMethodGroup() { var source = @" unsafe class C { static void M() { _ = &(() => {}!); _ = &(M!); } }"; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics( // (6,15): error CS0211: Cannot take the address of the given expression // _ = &(() => {}!); Diagnostic(ErrorCode.ERR_InvalidAddrOp, "() => {}").WithLocation(6, 15), // (7,15): error CS0211: Cannot take the address of the given expression // _ = &(M!); Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M").WithArguments("M", "method group").WithLocation(7, 15) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void SuppressNullableWarning_AddressOf() { var source = @" unsafe class C { static void M(C x) { C* y1 = &x; C* y2 = &x!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypes(TestOptions.UnsafeReleaseDll, NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (6,9): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C') // C* y1 = &x; Diagnostic(ErrorCode.ERR_ManagedAddr, "C*").WithArguments("C").WithLocation(6, 9), // (6,26): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C') // C* y1 = &x; Diagnostic(ErrorCode.ERR_ManagedAddr, "&x").WithArguments("C").WithLocation(6, 26), // (6,26): warning CS8619: Nullability of reference types in value of type 'C*' doesn't match target type 'C*'. // C* y1 = &x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "&x").WithArguments("C*", "C*").WithLocation(6, 26), // (7,9): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C') // C* y2 = &x!; Diagnostic(ErrorCode.ERR_ManagedAddr, "C*").WithArguments("C").WithLocation(7, 9), // (7,26): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C') // C* y2 = &x!; Diagnostic(ErrorCode.ERR_ManagedAddr, "&x!").WithArguments("C").WithLocation(7, 26), // (7,26): warning CS8619: Nullability of reference types in value of type 'C*' doesn't match target type 'C*'. // C* y2 = &x!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "&x!").WithArguments("C*", "C*").WithLocation(7, 26), // (7,27): error CS8598: The suppression operator is not allowed in this context // C* y2 = &x!; Diagnostic(ErrorCode.ERR_IllegalSuppression, "x").WithLocation(7, 27) ); } [Fact] public void SuppressNullableWarning_Invocation() { var source = @" class C { void M() { _ = nameof!(M); _ = typeof!(C); this.M!(); dynamic d = null!; d.M2!(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): error CS0103: The name 'nameof' does not exist in the current context // _ = nameof!(M); Diagnostic(ErrorCode.ERR_NameNotInContext, "nameof").WithArguments("nameof").WithLocation(6, 13), // (7,19): error CS1003: Syntax error, '(' expected // _ = typeof!(C); Diagnostic(ErrorCode.ERR_SyntaxError, "!").WithArguments("(", "!").WithLocation(7, 19), // (7,19): error CS1031: Type expected // _ = typeof!(C); Diagnostic(ErrorCode.ERR_TypeExpected, "!").WithLocation(7, 19), // (7,19): error CS1026: ) expected // _ = typeof!(C); Diagnostic(ErrorCode.ERR_CloseParenExpected, "!").WithLocation(7, 19), // (7,21): error CS0119: 'C' is a type, which is not valid in the given context // _ = typeof!(C); Diagnostic(ErrorCode.ERR_BadSKunknown, "C").WithArguments("C", "type").WithLocation(7, 21), // (8,9): error CS8598: The suppression operator is not allowed in this context // this.M!(); Diagnostic(ErrorCode.ERR_IllegalSuppression, "this.M").WithLocation(8, 9), // (10,9): error CS8598: The suppression operator is not allowed in this context // d.M2!(); Diagnostic(ErrorCode.ERR_IllegalSuppression, "d.M2").WithLocation(10, 9) ); } [Fact, WorkItem(31584, "https://github.com/dotnet/roslyn/issues/31584")] public void Verify31584() { var comp = CreateCompilation(@" using System; using System.Linq; class C { void M(Func? predicate) { var items = Enumerable.Empty(); if (predicate != null) items = items.Where(x => predicate(x)); } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(32463, "https://github.com/dotnet/roslyn/issues/32463")] public void Verify32463() { var comp = CreateCompilation(@" using System.Linq; class C { public void F(string? param) { if (param != null) _ = new[] { 0 }.Select(_ => param.Length); string? local = """"; if (local != null) _ = new[] { 0 }.Select(_ => local.Length); } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(32701, "https://github.com/dotnet/roslyn/issues/32701")] public void Verify32701() { var source = @" class C { static void M(ref T t, dynamic? d) { t = d; // 1 } static void M2(T t, dynamic? d) { t = d; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8601: Possible null reference assignment. // t = d; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "d").WithLocation(6, 13), // (10,13): warning CS8601: Possible null reference assignment. // t = d; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "d").WithLocation(10, 13) ); } [Fact, WorkItem(26696, "https://github.com/dotnet/roslyn/issues/26696")] public void Verify26696() { var source = @" interface I { object this[int i] { get; } } class C : I { T this[int i] => throw null!; object I.this[int i] => this[i]!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefReturn() { var source = @" struct S { ref S M(ref S x) { return ref x; // 1 } ref S M2(ref S x) { return ref x!; } } class C { ref C? M3(ref C x) { return ref x; // 2 } ref C M4(ref C? x) { return ref x; // 3 } ref C? M5(ref C x) { return ref x!; } ref C M6(ref C? x) { return ref x!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,20): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S'. // return ref x; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("S", "S").WithLocation(6, 20), // (17,20): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C?'. // return ref x; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C?").WithLocation(17, 20), // (21,20): warning CS8619: Nullability of reference types in value of type 'C?' doesn't match target type 'C'. // return ref x; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C?", "C").WithLocation(21, 20) ); } [Fact, WorkItem(33982, "https://github.com/dotnet/roslyn/issues/33982")] public void RefReturn_Lambda() { var comp = CreateCompilation(@" delegate ref V D(ref T t, ref U u); interface I { } interface IIn { } interface IOut { } class C { static V F(D d) => throw null!; void M(bool b) { F((ref object? x, ref object y) => { if (b) return ref x; return ref y; }); // 1 F((ref object? x, ref object y) => { if (b) return ref y; return ref x; }); // 2 F((ref I x, ref I y) => { if (b) return ref x; return ref y; }); // 3 F((ref I x, ref I y) => { if (b) return ref y; return ref x; }); // 4 F((ref IOut x, ref IOut y) => { if (b) return ref x; return ref y; }); // 5 F((ref IOut x, ref IOut y) => { if (b) return ref y; return ref x; }); // 6 F((ref IIn x, ref IIn y) => { if (b) return ref x; return ref y; }); // 7 F((ref IIn x, ref IIn y) => { if (b) return ref y; return ref x; }); // 8 } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,47): warning CS8619: Nullability of reference types in value of type 'object' doesn't match target type 'object?'. // { if (b) return ref x; return ref y; }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("object", "object?").WithLocation(12, 47), // (14,33): warning CS8619: Nullability of reference types in value of type 'object' doesn't match target type 'object?'. // { if (b) return ref y; return ref x; }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("object", "object?").WithLocation(14, 33), // (17,33): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // { if (b) return ref x; return ref y; }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(17, 33), // (19,47): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // { if (b) return ref y; return ref x; }); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(19, 47), // (22,47): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // { if (b) return ref x; return ref y; }); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(22, 47), // (24,33): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // { if (b) return ref y; return ref x; }); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(24, 33), // (27,33): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // { if (b) return ref x; return ref y; }); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(27, 33), // (29,47): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // { if (b) return ref y; return ref x; }); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(29, 47) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefReturn_State() { var source = @" class C { ref C M1(ref C? w) { return ref w; // 1 } ref C? M2(ref C w) { return ref w; // 2 } ref C M3(ref C w) { return ref w; } ref C? M4(ref C? w) { return ref w; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,20): warning CS8619: Nullability of reference types in value of type 'C?' doesn't match target type 'C'. // return ref w; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("C?", "C").WithLocation(6, 20), // (10,20): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C?'. // return ref w; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("C", "C?").WithLocation(10, 20) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefAssignment() { var source = @" class C { void M1(C? x) { ref C y = ref x; // 1 y.ToString(); // 2 } void M2(C x) { ref C? y = ref x; // 3 y.ToString(); } void M3(C? x, C nonNull) { x = nonNull; ref C y = ref x; // 4 y.ToString(); y = null; // 5 } void M4(C x, C? nullable) { x = nullable; // 6 ref C? y = ref x; // 7 y.ToString(); // 8 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,23): warning CS8619: Nullability of reference types in value of type 'C?' doesn't match target type 'C'. // ref C y = ref x; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C?", "C").WithLocation(6, 23), // (7,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(7, 9), // (11,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C?'. // ref C? y = ref x; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C?").WithLocation(11, 24), // (17,23): warning CS8619: Nullability of reference types in value of type 'C?' doesn't match target type 'C'. // ref C y = ref x; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C?", "C").WithLocation(17, 23), // (19,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // y = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 13), // (23,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = nullable; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "nullable").WithLocation(23, 13), // (24,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C?'. // ref C? y = ref x; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C?").WithLocation(24, 24), // (25,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(25, 9) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefAssignment_WithSuppression() { var source = @" class C { void M1(C? x) { ref C y = ref x!; y.ToString(); } void M2(C x) { ref C? y = ref x!; y.ToString(); } void M3(C? x, C nonNull) { x = nonNull; ref C y = ref x!; y.ToString(); } void M4(C x, C? nullable) { x = nullable; // 1 ref C? y = ref x!; y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (22,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = nullable; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "nullable").WithLocation(22, 13) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefAssignment_Nested() { var source = @" struct S { void M(ref S x) { S y = default; ref S y2 = ref y; // 1 y2 = ref y; // 2 y2 = ref y!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,32): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S'. // ref S y2 = ref y; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("S", "S").WithLocation(7, 32), // (8,18): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S'. // y2 = ref y; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("S", "S").WithLocation(8, 18) ); } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefAssignment_Foreach() { verify(variableType: "string?", itemType: "string", // (6,18): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // foreach (ref string? item in collection) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "ref string?").WithArguments("string", "string?").WithLocation(6, 18)); verify("string", "string?", // (6,18): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // foreach (ref string item in collection) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "ref string").WithArguments("string?", "string").WithLocation(6, 18), // (8,13): warning CS8602: Dereference of a possibly null reference. // item.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(8, 13)); verify("string", "string"); verify("string?", "string?", // (8,13): warning CS8602: Dereference of a possibly null reference. // item.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(8, 13)); verify("C", "C", // (6,18): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // foreach (ref C item in collection) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "ref C").WithArguments("C", "C").WithLocation(6, 18)); verify("C", "C", // (6,18): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // foreach (ref C item in collection) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "ref C").WithArguments("C", "C").WithLocation(6, 18)); verify("C", "C?", // (6,18): warning CS8619: Nullability of reference types in value of type 'C?' doesn't match target type 'C'. // foreach (ref C item in collection) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "ref C").WithArguments("C?", "C").WithLocation(6, 18), // (8,13): warning CS8602: Dereference of a possibly null reference. // item.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(8, 13)); verify("C", "C"); verify("var", "string"); verify("var", "string?", // (8,13): warning CS8602: Dereference of a possibly null reference. // item.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(8, 13)); verify("T", "T", // (8,13): warning CS8602: Dereference of a possibly null reference. // item.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(8, 13)); void verify(string variableType, string itemType, params DiagnosticDescription[] expected) { var source = @" class C { void M(RefEnumerable collection) { foreach (ref VARTYPE item in collection) { item.ToString(); } } class RefEnumerable { public StructEnum GetEnumerator() => throw null!; public struct StructEnum { public ref ITEMTYPE Current => throw null!; public bool MoveNext() => throw null!; } } }"; var comp = CreateCompilation(source.Replace("VARTYPE", variableType).Replace("ITEMTYPE", itemType), options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(expected); } } [Fact, WorkItem(31297, "https://github.com/dotnet/roslyn/issues/31297")] public void RefAssignment_Foreach_Nested() { verify(fieldType: "string?", // (9,13): warning CS8602: Dereference of a possibly null reference. // item.Field.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item.Field").WithLocation(9, 13)); verify(fieldType: "string", // (4,19): warning CS8618: Non-nullable field 'Field' is uninitialized. // public string Field; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Field").WithArguments("field", "Field").WithLocation(4, 19)); void verify(string fieldType, params DiagnosticDescription[] expected) { var source = @" class C { public FIELDTYPE Field; void M(RefEnumerable collection) { foreach (ref C item in collection) { item.Field.ToString(); } } class RefEnumerable { public StructEnum GetEnumerator() => throw null!; public struct StructEnum { public ref C Current => throw null!; public bool MoveNext() => throw null!; } } }"; var comp = CreateCompilation(source.Replace("FIELDTYPE", fieldType), options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(expected); } } [Fact] public void RefAssignment_Inferred() { var source = @" class C { void M1(C x) { ref var y = ref x; y = null; // 1 x.ToString(); y.ToString(); // 2 } void M2(C? x) { ref var y = ref x; y = null; x.ToString(); // 3 y.ToString(); // 4 } void M3(C? x) { ref var y = ref x; x.ToString(); // 5 y.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // y = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 13), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(16, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(17, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(23, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(24, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void TestLambdaWithError19() { var source = @"using System; using System.Linq.Expressions; class Program { static void Main(string[] args) { Ma(string.Empty, ((x, y) => x.ToString())!); Mb(string.Empty, ((x, y) => x.ToString())!); Mc(string.Empty, ((x, y) => x.ToString())!); } static void Ma(T t, Expression> action) { } static void Mb(T t, Expression> action) { } static void Mb(T t, Action action) { } static void Mc(T t, Expression> action) { } static void Mc() { } } "; var compilation = CreateCompilationWithMscorlib40AndSystemCore(source); var tree = compilation.SyntaxTrees[0]; var sm = compilation.GetSemanticModel(tree); foreach (var lambda in tree.GetRoot().DescendantNodes().OfType()) { var reference = lambda.Body.DescendantNodesAndSelf().OfType().First(); Assert.Equal("x", reference.ToString()); var typeInfo = sm.GetTypeInfo(reference); Assert.Equal(TypeKind.Class, typeInfo.Type.TypeKind); Assert.Equal("String", typeInfo.Type.Name); Assert.NotEmpty(typeInfo.Type.GetMembers("Replace")); } } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_DelegateComparison() { var source = @" class C { static void M() { System.Func x = null; _ = x == (() => 1)!; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,13): error CS0019: Operator '==' cannot be applied to operands of type 'Func' and 'lambda expression' // _ = x == (() => 1)!; Diagnostic(ErrorCode.ERR_BadBinaryOps, "x == (() => 1)!").WithArguments("==", "System.Func", "lambda expression").WithLocation(7, 13) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_ArgList() { var source = @" class C { static void M() { _ = __arglist!; M(__arglist(__arglist()!)); } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,13): error CS0190: The __arglist construct is valid only within a variable argument method // _ = __arglist!; Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(6, 13), // (7,21): error CS0226: An __arglist expression may only appear inside of a call or new expression // M(__arglist(__arglist()!)); Diagnostic(ErrorCode.ERR_IllegalArglist, "__arglist()").WithLocation(7, 21) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void BadInvocationInLambda() { var src = @" using System; using System.Linq.Expressions; class C { Expression> e = x => new object[](x); Expression> e2 = x => new object[](x)!; }"; // Suppressed expression cannot be used as a statement var comp = CreateCompilationWithMscorlib40AndSystemCore(src); comp.VerifyDiagnostics( // (7,52): error CS1586: Array creation must have array size or array initializer // Expression> e = x => new object[](x); Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(7, 52), // (8,53): error CS1586: Array creation must have array size or array initializer // Expression> e2 = x => new object[](x)!; Diagnostic(ErrorCode.ERR_MissingArraySize, "[]").WithLocation(8, 53), // (8,43): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // Expression> e2 = x => new object[](x)!; Diagnostic(ErrorCode.ERR_IllegalStatement, "new object[](x)!").WithLocation(8, 43) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_AsStatement() { var src = @" class C { void M2(string x) { x!; M2(x)!; } string M(string x) { x!; M(x)!; throw null!; } }"; // Suppressed expression cannot be used as a statement var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (6,9): error CS8598: The suppression operator is not allowed in this context // x!; Diagnostic(ErrorCode.ERR_IllegalSuppression, "x").WithLocation(6, 9), // (6,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // x!; Diagnostic(ErrorCode.ERR_IllegalStatement, "x!").WithLocation(6, 9), // (7,9): error CS8598: The suppression operator is not allowed in this context // M2(x)!; Diagnostic(ErrorCode.ERR_IllegalSuppression, "M2(x)").WithLocation(7, 9), // (7,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // M2(x)!; Diagnostic(ErrorCode.ERR_IllegalStatement, "M2(x)!").WithLocation(7, 9), // (11,9): error CS8598: The suppression operator is not allowed in this context // x!; Diagnostic(ErrorCode.ERR_IllegalSuppression, "x").WithLocation(11, 9), // (11,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // x!; Diagnostic(ErrorCode.ERR_IllegalStatement, "x!").WithLocation(11, 9), // (12,9): error CS8598: The suppression operator is not allowed in this context // M(x)!; Diagnostic(ErrorCode.ERR_IllegalSuppression, "M(x)").WithLocation(12, 9), // (12,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // M(x)!; Diagnostic(ErrorCode.ERR_IllegalStatement, "M(x)!").WithLocation(12, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_VoidInvocation() { var src = @" class C { void M() { _ = M()!; } }"; var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (6,9): error CS8209: A value of type 'void' may not be assigned. // _ = M()!; Diagnostic(ErrorCode.ERR_VoidAssignment, "_").WithLocation(6, 9) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void CS0023ERR_BadUnaryOp_lambdaExpression() { var text = @" class X { static void Main() { System.Func f = (arg => { arg = 2; return arg; } !).ToString(); var x = (delegate { } !).ToString(); } } "; CreateCompilation(text).VerifyDiagnostics( // (6,35): error CS0023: Operator '.' cannot be applied to operand of type 'lambda expression' // System.Func f = (arg => { arg = 2; return arg; } !).ToString(); Diagnostic(ErrorCode.ERR_BadUnaryOp, "(arg => { arg = 2; return arg; } !).ToString").WithArguments(".", "lambda expression").WithLocation(6, 35), // (8,17): error CS0023: Operator '.' cannot be applied to operand of type 'anonymous method' // var x = (delegate { } !).ToString(); Diagnostic(ErrorCode.ERR_BadUnaryOp, "(delegate { } !).ToString").WithArguments(".", "anonymous method").WithLocation(8, 17) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void ConditionalMemberAccess001() { var text = @" class Program { static void Main(string[] args) { var x4 = (()=> { return 1; } !) ?.ToString(); } } "; CreateCompilationWithMscorlib45(text).VerifyDiagnostics( // (6,18): error CS0023: Operator '?' cannot be applied to operand of type 'lambda expression' // var x4 = (()=> { return 1; } !) ?.ToString(); Diagnostic(ErrorCode.ERR_BadUnaryOp, "(()=> { return 1; } !) ?.ToString()").WithArguments("?", "lambda expression").WithLocation(6, 18), // (6,18): error CS0023: Operator '?' cannot be applied to operand of type 'lambda expression' // var x4 = (()=> { return 1; } !) ?.ToString(); Diagnostic(ErrorCode.ERR_BadUnaryOp, "(()=> { return 1; } !) ?.ToString()").WithArguments("?", "lambda expression").WithLocation(6, 18) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void DynamicCollectionInitializer_Errors() { string source = @" using System; unsafe class C { public dynamic X; public static int* ptr = null; static void M() { var c = new C { X = { M!, ptr!, () => {}!, default(TypedReference)!, M()!, __arglist } }; } } "; // Should `!` be disallowed on arguments to dynamic? // See https://github.com/dotnet/roslyn/issues/32364 CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (15,17): error CS1976: Cannot use a method group as an argument to a dynamically dispatched operation. Did you intend to invoke the method? // M!, Diagnostic(ErrorCode.ERR_BadDynamicMethodArgMemgrp, "M").WithLocation(15, 17), // (16,17): error CS1978: Cannot use an expression of type 'int*' as an argument to a dynamically dispatched operation. // ptr!, Diagnostic(ErrorCode.ERR_BadDynamicMethodArg, "ptr").WithArguments("int*").WithLocation(16, 17), // (17,17): error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. // () => {}!, Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "() => {}").WithLocation(17, 17), // (18,17): error CS1978: Cannot use an expression of type 'TypedReference' as an argument to a dynamically dispatched operation. // default(TypedReference)!, Diagnostic(ErrorCode.ERR_BadDynamicMethodArg, "default(TypedReference)").WithArguments("System.TypedReference").WithLocation(18, 17), // (19,17): error CS1978: Cannot use an expression of type 'void' as an argument to a dynamically dispatched operation. // M()!, Diagnostic(ErrorCode.ERR_BadDynamicMethodArg, "M()").WithArguments("void").WithLocation(19, 17), // (20,17): error CS0190: The __arglist construct is valid only within a variable argument method // __arglist Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(20, 17), // (20,17): error CS1978: Cannot use an expression of type 'RuntimeArgumentHandle' as an argument to a dynamically dispatched operation. // __arglist Diagnostic(ErrorCode.ERR_BadDynamicMethodArg, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(20, 17) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void TestNullCoalesceWithMethodGroup() { var source = @" using System; class Program { static void Main() { Action a = Main! ?? Main; Action a2 = Main ?? Main!; } } "; CreateCompilation(source).VerifyDiagnostics( // (8,20): error CS0019: Operator '??' cannot be applied to operands of type 'method group' and 'method group' // Action a = Main! ?? Main; Diagnostic(ErrorCode.ERR_BadBinaryOps, "Main! ?? Main").WithArguments("??", "method group", "method group").WithLocation(8, 20), // (9,21): error CS0019: Operator '??' cannot be applied to operands of type 'method group' and 'method group' // Action a2 = Main ?? Main!; Diagnostic(ErrorCode.ERR_BadBinaryOps, "Main ?? Main!").WithArguments("??", "method group", "method group").WithLocation(9, 21) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_IsAsOperatorWithBadSuppressedExpression() { var source = @" class C { void M() { _ = (() => {}!) is null; // 1 _ = (M!) is null; // 2 _ = (null, null)! is object; // 3 _ = null! is object; // 4 _ = default! is object; // 5 _ = (() => {}!) as object; // 6 _ = (M!) as object; // 7 _ = (null, null)! as object; // 8 _ = null! as object; // ok _ = default! as string; // 10 } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,13): error CS0837: The first operand of an 'is' or 'as' operator may not be a lambda expression, anonymous method, or method group. // _ = (() => {}!) is null; // 1 Diagnostic(ErrorCode.ERR_LambdaInIsAs, "(() => {}!) is null").WithLocation(6, 13), // (7,13): error CS0837: The first operand of an 'is' or 'as' operator may not be a lambda expression, anonymous method, or method group. // _ = (M!) is null; // 2 Diagnostic(ErrorCode.ERR_LambdaInIsAs, "(M!) is null").WithLocation(7, 13), // (8,13): error CS0023: Operator 'is' cannot be applied to operand of type '(, )' // _ = (null, null)! is object; // 3 Diagnostic(ErrorCode.ERR_BadUnaryOp, "(null, null)! is object").WithArguments("is", "(, )").WithLocation(8, 13), // (9,13): warning CS0184: The given expression is never of the provided ('object') type // _ = null! is object; // 4 Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "null! is object").WithArguments("object").WithLocation(9, 13), // (10,13): error CS0023: Operator 'is' cannot be applied to operand of type 'default' // _ = default! is object; // 5 Diagnostic(ErrorCode.ERR_BadUnaryOp, "default! is object").WithArguments("is", "default").WithLocation(10, 13), // (12,13): error CS0837: The first operand of an 'is' or 'as' operator may not be a lambda expression, anonymous method, or method group. // _ = (() => {}!) as object; // 6 Diagnostic(ErrorCode.ERR_LambdaInIsAs, "(() => {}!) as object").WithLocation(12, 13), // (13,13): error CS0837: The first operand of an 'is' or 'as' operator may not be a lambda expression, anonymous method, or method group. // _ = (M!) as object; // 7 Diagnostic(ErrorCode.ERR_LambdaInIsAs, "(M!) as object").WithLocation(13, 13), // (14,13): error CS8307: The first operand of an 'as' operator may not be a tuple literal without a natural type. // _ = (null, null)! as object; // 8 Diagnostic(ErrorCode.ERR_TypelessTupleInAs, "(null, null)! as object").WithLocation(14, 13), // (16,13): warning CS0458: The result of the expression is always 'null' of type 'string' // _ = default! as string; // 10 Diagnostic(ErrorCode.WRN_AlwaysNull, "default! as string").WithArguments("string").WithLocation(16, 13) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void ImplicitDelegateCreationWithIncompleteLambda() { var source = @" using System; class C { public void F() { Action x = (i => i.)! } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,33): error CS1001: Identifier expected // Action x = (i => i.)! Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(7, 33), // (7,35): error CS1002: ; expected // Action x = (i => i.)! Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(7, 35), // (7,31): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // Action x = (i => i.)! Diagnostic(ErrorCode.ERR_IllegalStatement, "i.").WithLocation(7, 31) ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var lambda = tree.GetRoot().DescendantNodes().Where(n => n.IsKind(SyntaxKind.SimpleLambdaExpression)).Single(); var param = lambda.ChildNodes().Where(n => n.IsKind(SyntaxKind.Parameter)).Single(); var symbol1 = model.GetDeclaredSymbol(param); Assert.Equal("System.Int32 i", symbol1.ToTestDisplayString()); var id = lambda.DescendantNodes().First(n => n.IsKind(SyntaxKind.IdentifierName)); var symbol2 = model.GetSymbolInfo(id).Symbol; Assert.Equal("System.Int32 i", symbol2.ToTestDisplayString()); Assert.Same(symbol1, symbol2); } [Fact, WorkItem(32179, "https://github.com/dotnet/roslyn/issues/32179")] public void SuppressNullableWarning_DefaultStruct() { var source = @"public struct S { public string field; } public class C { public S field; void M() { S s = default; // assigns null to S.field _ = s; _ = new C(); // assigns null to C.S.field } }"; // We should probably warn for such scenarios (either in the definition of S, or in the usage of S) // Tracked by https://github.com/dotnet/roslyn/issues/32179 var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_ThrowNull() { var source = @"class C { void M() { throw null!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_ThrowExpression() { var source = @"class C { void M() { (throw null!)!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // (throw null!)!; Diagnostic(ErrorCode.ERR_IllegalStatement, "(throw null!)!").WithLocation(5, 9), // (5,10): error CS8115: A throw expression is not allowed in this context. // (throw null!)!; Diagnostic(ErrorCode.ERR_ThrowMisplaced, "throw").WithLocation(5, 10) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_IsNull() { var source = @"class C { bool M(object o) { return o is null!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); CompileAndVerify(comp); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MiscNull() { var source = @" using System.Linq.Expressions; class C { void M(object o, int? i) { _ = null is object; // 1 _ = null! is object; // 2 int i2 = null!; // 3 var i3 = (int)null!; // 4 T t = null!; // 5 var t2 = (T)null!; // 6 _ = null == null!; _ = (null!, null) == (null, null!); (null)++; // 9 (null!)++; // 10 _ = !null; // 11 _ = !(null!); // 12 Expression> testExpr = () => null! ?? ""hello""; // 13 _ = o == null; _ = o == null!; // 14 _ = null ?? o; _ = null! ?? o; _ = i == null; _ = i == null!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS0184: The given expression is never of the provided ('object') type // _ = null is object; // 1 Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "null is object").WithArguments("object").WithLocation(7, 13), // (8,13): warning CS0184: The given expression is never of the provided ('object') type // _ = null! is object; // 2 Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "null! is object").WithArguments("object").WithLocation(8, 13), // (10,18): error CS0037: Cannot convert null to 'int' because it is a non-nullable value type // int i2 = null!; // 3 Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(10, 18), // (11,18): error CS0037: Cannot convert null to 'int' because it is a non-nullable value type // var i3 = (int)null!; // 4 Diagnostic(ErrorCode.ERR_ValueCantBeNull, "(int)null!").WithArguments("int").WithLocation(11, 18), // (12,15): error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead. // T t = null!; // 5 Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(12, 15), // (13,18): error CS0037: Cannot convert null to 'T' because it is a non-nullable value type // var t2 = (T)null!; // 6 Diagnostic(ErrorCode.ERR_ValueCantBeNull, "(T)null!").WithArguments("T").WithLocation(13, 18), // (16,10): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer // (null)++; // 9 Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "null").WithLocation(16, 10), // (17,10): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer // (null!)++; // 10 Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "null").WithLocation(17, 10), // (18,13): error CS8310: Operator '!' cannot be applied to operand '' // _ = !null; // 11 Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!null").WithArguments("!", "").WithLocation(18, 13), // (19,13): error CS8310: Operator '!' cannot be applied to operand '' // _ = !(null!); // 12 Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "!(null!)").WithArguments("!", "").WithLocation(19, 13), // (20,58): error CS0845: An expression tree lambda may not contain a coalescing operator with a null or default literal left-hand side // Expression> testExpr = () => null! ?? "hello"; // 13 Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null").WithLocation(20, 58) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_MiscDefault() { var source = @"class C { void M(dynamic d, int? i) { d.M(null!, default!, null, default); // 1 _ = default == default!; // 2 _ = default! == default!; // 3 _ = 1 + default!; // 4 _ = default ?? d; // 5 _ = default! ?? d; // 6 _ = i ?? default; _ = i ?? default!; } void M2(object o) { _ = o == default; // 7 _ = o == default!; // 8 } }"; // Should `!` be disallowed on arguments to dynamic (line // 1) ? // See https://github.com/dotnet/roslyn/issues/32364 var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): error CS8311: Cannot use a default literal as an argument to a dynamically dispatched operation. // d.M(null!, default!, null, default); // 1 Diagnostic(ErrorCode.ERR_BadDynamicMethodArgDefaultLiteral, "default").WithLocation(5, 20), // (5,36): error CS8311: Cannot use a default literal as an argument to a dynamically dispatched operation. // d.M(null!, default!, null, default); // 1 Diagnostic(ErrorCode.ERR_BadDynamicMethodArgDefaultLiteral, "default").WithLocation(5, 36), // (6,13): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // _ = default == default!; // 2 Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default == default!").WithArguments("==").WithLocation(6, 13), // (7,13): error CS8315: Operator '==' is ambiguous on operands 'default' and 'default' // _ = default! == default!; // 3 Diagnostic(ErrorCode.ERR_AmbigBinaryOpsOnDefault, "default! == default!").WithArguments("==").WithLocation(7, 13), // (8,13): error CS8310: Operator '+' cannot be applied to operand 'default' // _ = 1 + default!; // 4 Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 + default!").WithArguments("+", "default").WithLocation(8, 13), // (9,13): error CS8310: Operator '??' cannot be applied to operand 'default' // _ = default ?? d; // 5 Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default ?? d").WithArguments("??", "default").WithLocation(9, 13), // (10,13): error CS8310: Operator '??' cannot be applied to operand 'default' // _ = default! ?? d; // 6 Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default! ?? d").WithArguments("??", "default").WithLocation(10, 13) ); } [Fact, WorkItem(32879, "https://github.com/dotnet/roslyn/issues/32879")] public void ThrowExpressionInNullCoalescingOperator() { var source = @" class C { string Field = string.Empty; void M(C? c) { _ = c ?? throw new System.ArgumentNullException(nameof(c)); c.ToString(); } void M2(C? c) { _ = c?.Field ?? throw new System.ArgumentNullException(nameof(c)); c.ToString(); c.Field.ToString(); } void M3(C? c) { _ = c ?? throw new System.ArgumentNullException(c.ToString()); // 1 } void M4(string? s) { _ = s ?? s.ToString(); // 2 s.ToString(); } void M5(string s) { _ = s ?? s.ToString(); // 3 } #nullable disable void M6(string s) { #nullable enable _ = s ?? s.ToString(); // 4 } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (18,57): warning CS8602: Dereference of a possibly null reference. // _ = c ?? throw new System.ArgumentNullException(c.ToString()); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(18, 57), // (22,18): warning CS8602: Dereference of a possibly null reference. // _ = s ?? s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(22, 18), // (27,18): warning CS8602: Dereference of a possibly null reference. // _ = s ?? s.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(27, 18), // (33,18): warning CS8602: Dereference of a possibly null reference. // _ = s ?? s.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(33, 18)); } [Fact, WorkItem(32877, "https://github.com/dotnet/roslyn/issues/32877")] public void CheckReceiverOfThrow() { var source = @" class C { void M(System.Exception? e, C? c) { _ = c ?? throw e; // 1 _ = c ?? throw null; // 2 throw null; // 3 } void M2(System.Exception? e, bool b) { if (b) throw e; // 4 else throw e!; } void M3() { throw this; // 5 } public static implicit operator System.Exception?(C c) => throw null!; void M4(TException? e) where TException : System.Exception { throw e; // 6 } void M5(TException e) where TException : System.Exception? { throw e; // 7 } void M6(TException? e) where TException : Interface { throw e; // 8 } void M7(TException e) where TException : Interface? { throw e; // 9 } void M8(TException e) where TException : Interface { throw e; // 10 } void M9(T e) { throw e; // 11 } void M10() { try { } catch { throw; } } interface Interface { } }"; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,24): error CS8597: Thrown value may be null. // _ = c ?? throw e; // 1 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(6, 24), // (7,24): error CS8597: Thrown value may be null. // _ = c ?? throw null; // 2 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "null").WithLocation(7, 24), // (8,15): error CS8597: Thrown value may be null. // throw null; // 3 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "null").WithLocation(8, 15), // (13,19): error CS8597: Thrown value may be null. // throw e; // 4 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(13, 19), // (19,15): error CS0155: The type caught or thrown must be derived from System.Exception // throw this; // 5 Diagnostic(ErrorCode.ERR_BadExceptionType, "this").WithLocation(19, 15), // (24,15): error CS8597: Thrown value may be null. // throw e; // 6 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(24, 15), // (28,15): error CS8597: Thrown value may be null. // throw e; // 7 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(28, 15), // (30,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void M6(TException? e) where TException : Interface Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "TException?").WithLocation(30, 25), // (32,15): error CS0155: The type caught or thrown must be derived from System.Exception // throw e; // 8 Diagnostic(ErrorCode.ERR_BadExceptionType, "e").WithLocation(32, 15), // (32,15): error CS8597: Thrown value may be null. // throw e; // 8 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(32, 15), // (36,15): error CS0155: The type caught or thrown must be derived from System.Exception // throw e; // 9 Diagnostic(ErrorCode.ERR_BadExceptionType, "e").WithLocation(36, 15), // (36,15): error CS8597: Thrown value may be null. // throw e; // 9 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(36, 15), // (40,15): error CS0155: The type caught or thrown must be derived from System.Exception // throw e; // 10 Diagnostic(ErrorCode.ERR_BadExceptionType, "e").WithLocation(40, 15), // (44,15): error CS0155: The type caught or thrown must be derived from System.Exception // throw e; // 11 Diagnostic(ErrorCode.ERR_BadExceptionType, "e").WithLocation(44, 15), // (44,15): error CS8597: Thrown value may be null. // throw e; // 11 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(44, 15) ); } [Fact, WorkItem(32877, "https://github.com/dotnet/roslyn/issues/32877")] public void CatchClause() { var source = @" class C { void M() { try { } catch (System.Exception? e) { throw e; } } void M2() { try { } catch (System.Exception? e) { throw; } } void M3() { try { } catch (System.Exception? e) { e = null; throw e; // 1 } } void M4() { try { } catch (System.Exception e) { e = null; // 2 throw e; // 3 } } void M5() { try { } catch (System.Exception e) { e = null; // 4 throw; // this rethrows the original exception, not an NRE } } }"; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,34): warning CS0168: The variable 'e' is declared but never used // catch (System.Exception? e) { throw; } Diagnostic(ErrorCode.WRN_UnreferencedVar, "e").WithArguments("e").WithLocation(12, 34), // (20,19): error CS8597: Thrown value may be null. // throw e; // 1 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(20, 19), // (28,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // e = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(28, 17), // (29,19): error CS8597: Thrown value may be null. // throw e; // 3 Diagnostic(ErrorCode.WRN_ThrowPossibleNull, "e").WithLocation(29, 19), // (35,33): warning CS0168: The variable 'e' is declared but never used // catch (System.Exception e) Diagnostic(ErrorCode.WRN_UnreferencedVar, "e").WithArguments("e").WithLocation(35, 33), // (37,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // e = null; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(37, 17) ); } [Fact] public void Test0() { var source = @" class C { static void Main() { string? x = null; } } "; var c = CreateCompilation(source, parseOptions: TestOptions.Regular7); c.VerifyDiagnostics( // (6,15): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // string? x = null; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(6, 15), // (6,17): warning CS0219: The variable 'x' is assigned but its value is never used // string? x = null; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(6, 17) ); var c2 = CreateCompilation(source, parseOptions: TestOptions.Regular8); c2.VerifyDiagnostics( // (6,15): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? x = null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 15), // (6,17): warning CS0219: The variable 'x' is assigned but its value is never used // string? x = null; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(6, 17) ); } [Fact] public void SpeakableInference_MethodTypeInference() { var source = @"class Program { void M(T t) { if (t == null) throw null!; t.ToString(); var t2 = Copy(t); t2.ToString(); // warn } static T Copy(T t) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(8, 9) ); } [Fact] public void SpeakableInference_MethodTypeInference_WithTuple() { var source = @"class Program { void M(T t) { if (t == null) throw null!; var tuple = (t, t); tuple.Item1.ToString(); tuple.Item2.ToString(); var tuple2 = Copy(tuple); tuple2.Item1.ToString(); // warn tuple2.Item2.ToString(); // warn var tuple3 = Copy(tuple); tuple3.Item1.ToString(); // warn tuple3.Item2.ToString(); // warn } static (T, U) Copy((T, U) t) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // tuple2.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "tuple2.Item1").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // tuple2.Item2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "tuple2.Item2").WithLocation(12, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // tuple3.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "tuple3.Item1").WithLocation(15, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // tuple3.Item2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "tuple3.Item2").WithLocation(16, 9) ); } [Fact] public void SpeakableInference_MethodTypeInference_WithNull() { var source = @"class Program { void M(T t) where T : class? { if (t == null) throw null!; t.ToString(); var t2 = Copy(t, null); t2.ToString(); // warn } static T Copy(T t, U t) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,18): error CS0411: The type arguments for method 'Program.Copy(T, U)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // var t2 = Copy(t, null); Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Copy").WithArguments("Program.Copy(T, U)").WithLocation(7, 18), // (10,32): error CS0100: The parameter name 't' is a duplicate // static T Copy(T t, U t) => throw null!; Diagnostic(ErrorCode.ERR_DuplicateParamName, "t").WithArguments("t").WithLocation(10, 32) ); } [Fact] public void SpeakableInference_MethodTypeInference_NullAssigned() { var source = @"class Program { void M(T t) where T : class { t = null; var t2 = Copy(t); t2 /*T:T?*/ .ToString(); // warn } static T Copy(T t) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (5,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // t = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // t2 /*T:T?*/ .ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(7, 9) ); } [Fact] public void SpeakableInference_MethodTypeInference_NullableValueType() { var source = @"class Program { void M(int? t) { if (t == null) throw null!; t.Value.ToString(); var t2 = Copy(t); t2.Value.ToString(); // warn } void M2(T? t) where T : struct { if (t == null) throw null!; t.Value.ToString(); var t2 = Copy(t); t2.Value.ToString(); // warn } static T Copy(T t) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8629: Nullable value type may be null. // t2.Value.ToString(); // warn Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(8, 9), // (15,9): warning CS8629: Nullable value type may be null. // t2.Value.ToString(); // warn Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(15, 9) ); } [Fact] public void SpeakableInference_ArrayTypeInference() { var source = @"class Program { void M(T t) { if (t == null) throw null!; t.ToString(); var t2 = new[] { t }; t2[0].ToString(); // warn } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t2[0].ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2[0]").WithLocation(8, 9) ); } [Fact] public void SpeakableInference_ArrayTypeInference_WithTuple() { var source = @"class Program { void M(T t) { if (t == null) throw null!; var a = new[] { (t, t) }; a[0].Item1.ToString(); a[0].Item2.ToString(); var b = new (T, T)[] { (t, t) }; b[0].Item1.ToString(); b[0].Item2.ToString(); } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // a[0].Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a[0].Item1").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // a[0].Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a[0].Item2").WithLocation(8, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // b[0].Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0].Item1").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // b[0].Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0].Item2").WithLocation(12, 9) ); } [Fact] public void SpeakableInference_ArrayTypeInference_WithNull() { var source = @"class Program { void M(T t) where T : class? { if (t == null) throw null!; t.ToString(); var t2 = new[] { t, null }; // 1 t2[0].ToString(); // warn // 2 } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,29): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // var t2 = new[] { t, null }; // 1 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(7, 29), // (8,9): warning CS8602: Dereference of a possibly null reference. // t2[0].ToString(); // warn // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2[0]").WithLocation(8, 9) ); } [Fact, WorkItem(30941, "https://github.com/dotnet/roslyn/issues/30941")] public void Verify30941() { var source = @" class Outer : Base { void M1(Base? x1) { Outer y = x1; } } class Base { } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,19): error CS0266: Cannot implicitly convert type 'Base' to 'Outer'. An explicit conversion exists (are you missing a cast?) // Outer y = x1; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x1").WithArguments("Base", "Outer").WithLocation(6, 19), // (6,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer y = x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(6, 19) ); } [Fact, WorkItem(31958, "https://github.com/dotnet/roslyn/issues/31958")] public void Verify31958() { var source = @" class C { string? M(string s) { var d = (D)M; d(null).ToString(); return null; } delegate string D(string? s); } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,17): warning CS8621: Nullability of reference types in return type of 'string? C.M(string s)' doesn't match the target delegate 'C.D'. // var d = (D)M; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "(D)M").WithArguments("string? C.M(string s)", "C.D").WithLocation(6, 17), // (6,17): warning CS8622: Nullability of reference types in type of parameter 's' of 'string? C.M(string s)' doesn't match the target delegate 'C.D'. // var d = (D)M; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(D)M").WithArguments("s", "string? C.M(string s)", "C.D").WithLocation(6, 17) ); } [Fact, WorkItem(28377, "https://github.com/dotnet/roslyn/issues/28377")] public void Verify28377() { var source = @" class C { void M() { object x; x! = null; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS0219: The variable 'x' is assigned but its value is never used // object x; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(6, 16), // (7,9): error CS8598: The suppression operator is not allowed in this context // x! = null; Diagnostic(ErrorCode.ERR_IllegalSuppression, "x").WithLocation(7, 9), // (7,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x! = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 14) ); } [Fact, WorkItem(31295, "https://github.com/dotnet/roslyn/issues/31295")] public void Verify31295() { var source = @" class C { void M() { for (var x = 0; ; x!++) { } } }"; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact, WorkItem(26654, "https://github.com/dotnet/roslyn/issues/26654")] public void Verify26654() { var source = @" public class C { public void M(out string? x) => throw null!; public void M2() { string y; M(out y!); } }"; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact, WorkItem(33782, "https://github.com/dotnet/roslyn/issues/33782")] public void AnnotationInXmlDoc_TwoDeclarations() { var source = @" /// public class C { void M(T? t) where T : struct { } void M(T t) where T : class { } /// /// See /// void M2() { } /// /// See /// void M3() { } }"; // In cref, `T?` always binds to `Nullable` var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithDocumentationComments, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var firstCref = tree.GetRoot().DescendantNodes(descendIntoTrivia: true).OfType().First(); var firstCrefSymbol = model.GetSymbolInfo(firstCref).Symbol; Assert.Equal("void C.M(T? t)", firstCrefSymbol.ToTestDisplayString()); var lastCref = tree.GetRoot().DescendantNodes(descendIntoTrivia: true).OfType().Last(); var lastCrefSymbol = model.GetSymbolInfo(lastCref).Symbol; Assert.Equal("void C.M(T t)", lastCrefSymbol.ToTestDisplayString()); } [Fact, WorkItem(33782, "https://github.com/dotnet/roslyn/issues/33782")] public void AnnotationInXmlDoc_DeclaredAsNonNullableReferenceType() { var source = @" /// public class C { void M(T t) where T : class { } /// /// warn 1 /// void M2() { } /// /// /// void M3() { } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithDocumentationComments, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,20): warning CS1574: XML comment has cref attribute 'M{T}(T?)' that could not be resolved // /// warn 1 Diagnostic(ErrorCode.WRN_BadXMLRef, "M{T}(T?)").WithArguments("M{T}(T?)").WithLocation(8, 20)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var lastCref = tree.GetRoot().DescendantNodes(descendIntoTrivia: true).OfType().Last(); var lastCrefSymbol = model.GetSymbolInfo(lastCref).Symbol; Assert.Equal("void C.M(T t)", lastCrefSymbol.ToTestDisplayString()); } [Fact, WorkItem(33782, "https://github.com/dotnet/roslyn/issues/33782")] public void AnnotationInXmlDoc_DeclaredAsNullableReferenceType() { var source = @" /// public class C { void M(T? t) where T : class { } /// /// warn 1 /// void M2() { } /// /// /// void M3() { } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithDocumentationComments, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,20): warning CS1574: XML comment has cref attribute 'M{T}(T?)' that could not be resolved // /// warn 1 Diagnostic(ErrorCode.WRN_BadXMLRef, "M{T}(T?)").WithArguments("M{T}(T?)").WithLocation(8, 20)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var lastCref = tree.GetRoot().DescendantNodes(descendIntoTrivia: true).OfType().Last(); var lastCrefSymbol = model.GetSymbolInfo(lastCref).Symbol; Assert.Equal("void C.M(T? t)", lastCrefSymbol.ToTestDisplayString()); } [Fact, WorkItem(30955, "https://github.com/dotnet/roslyn/issues/30955")] public void ArrayTypeInference_Verify30955() { var source = @" class Outer { void M0(object x0, object? y0) { var a = new[] { x0, 1 }; a[0] = y0; var b = new[] { x0, x0 }; b[0] = y0; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8601: Possible null reference assignment. // a[0] = y0; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y0").WithLocation(7, 16), // (9,16): warning CS8601: Possible null reference assignment. // b[0] = y0; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y0").WithLocation(9, 16) ); } [Fact, WorkItem(30598, "https://github.com/dotnet/roslyn/issues/30598")] public void Verify30598() { var source = @" class Program { static object F(object[]? x) { return x[ // warning: possibly null x.Length - 1]; // no warning } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8602: Dereference of a possibly null reference. // return x[ // warning: possibly null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 16) ); } [Fact, WorkItem(30925, "https://github.com/dotnet/roslyn/issues/30925")] public void Verify30925() { var source = @" class Outer { void M1(T x1, object? y1) where T : class? { x1 = (T)y1; } void M2(T x2, object? y2) where T : class? { x2 = y2; } void M3(string x3, object? y3) { x3 = (string)y3; } void M4(string x4, object? y4) { x4 = y4; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,14): warning CS8601: Possible null reference assignment. // x1 = (T)y1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)y1").WithLocation(6, 14), // (11,14): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // x2 = y2; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y2").WithArguments("object", "T").WithLocation(11, 14), // (11,14): warning CS8601: Possible null reference assignment. // x2 = y2; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y2").WithLocation(11, 14), // (16,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = (string)y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)y3").WithLocation(16, 14), // (21,14): error CS0266: Cannot implicitly convert type 'object' to 'string'. An explicit conversion exists (are you missing a cast?) // x4 = y4; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y4").WithArguments("object", "string").WithLocation(21, 14), // (21,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(21, 14)); } [Fact] public void SpeakableInference_ArrayTypeInference_NullableValueType() { var source = @"class Program { void M(int? t) { if (t == null) throw null!; t.Value.ToString(); var t2 = new[] { t }; t2[0].Value.ToString(); // warn } void M2(T? t) where T : struct { if (t == null) throw null!; t.Value.ToString(); var t2 = new[] { t }; t2[0].Value.ToString(); // warn } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8629: Nullable value type may be null. // t2[0].Value.ToString(); // warn Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2[0]").WithLocation(8, 9), // (15,9): warning CS8629: Nullable value type may be null. // t2[0].Value.ToString(); // warn Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2[0]").WithLocation(15, 9) ); } [Fact] public void SpeakableInference_ArrayTypeInference_ConversionWithNullableOutput_WithNestedMismatch() { var source = @"class A { public static implicit operator C?(A a) => throw null!; } class B : A { } class C { void M(B x, C y) { var a = new[] { x, y }; a[0].ToString(); var b = new[] { y, x }; b[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,25): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var a = new[] { x, y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(12, 25), // (13,9): warning CS8602: Dereference of a possibly null reference. // a[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a[0]").WithLocation(13, 9), // (15,28): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var b = new[] { y, x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(15, 28), // (16,9): warning CS8602: Dereference of a possibly null reference. // b[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(16, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference() { var source = @"class Program { void M(T t) { var x1 = F(() => { if (t == null) throw null!; bool b = true; if (b) return t; return t; }); x1.ToString(); var x2 = F(() => { if (t == null) throw null!; bool b = true; if (b) return t; return t; }); x2.ToString(); } T F(System.Func f) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(12, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(21, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference2() { var source = @"class Program { void M(T t, T t2) { var x1 = F(() => { if (t == null) throw null!; bool b = true; if (b) return t; return t2; }); x1.ToString(); var x2 = F(() => { if (t == null) throw null!; bool b = true; if (b) return t; return t2; }); x2.ToString(); } T F(System.Func f) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(12, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(21, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_WithSingleReturn() { var source = @"class Program { void M() { var x1 = Copy(() => """"); x1.ToString(); } void M2(T t) { if (t == null) throw null!; var x1 = Copy(() => t); x1.ToString(); // 1 } T Copy(System.Func f) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(12, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_WithTuple() { var source = @"class Program { void M(T t) { var x1 = Copy(() => { if (t == null) throw null!; bool b = true; if (b) return (t, t); return (t, t); }); x1.Item1.ToString(); x1.Item2.ToString(); } T Copy(System.Func f) => throw null!; }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x1.Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1.Item1").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // x1.Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1.Item2").WithLocation(13, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_ConversionWithNullableOutput() { var source = @"class A { public static implicit operator C?(A a) => new C(); } class B : A { } class C { void M(B x, C y) { var x1 = F(() => { bool b = true; if (b) return x; return y; }); x1.ToString(); var x2 = F(() => { bool b = true; if (b) return y; return x; }); x2.ToString(); } T F(System.Func f) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(18, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(26, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_ConversionWithNullableOutput2() { var source = @"class A { public static implicit operator C?(A a) => throw null!; } class B : A { } class C { void M(B x, C y) { var x1 = F(() => { bool b = true; if (b) return x; return y; }); x1.ToString(); var x2 = F(() => { bool b = true; if (b) return y; return x; }); x2.ToString(); } U F(System.Func f) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(18, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(26, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_ConversionWithNullableOutput_WithNestedMismatch() { var source = @"class A { public static implicit operator C?(A a) => throw null!; } class B : A { } class C { void M(B x, C y) { var x1 = F(() => { bool b = true; if (b) return x; return y; }); x1.ToString(); var x2 = F(() => { bool b = true; if (b) return y; return x; }); x2.ToString(); } U F(System.Func f) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,27): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // if (b) return x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(15, 27), // (18,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(18, 9), // (24,20): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // return x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(24, 20), // (26,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(26, 9) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_ConversionWithNullableInput() { var source = @"class A { public static implicit operator C(A? a) => null; // warn } class B : A { } class C { void M(B? x, C y) { var x1 = F(() => { bool b = true; if (b) return x; return y; }); x1.ToString(); var x2 = F(() => { bool b = true; if (b) return y; return x; }); x2.ToString(); } T F(System.Func f) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,48): warning CS8603: Possible null reference return. // public static implicit operator C(A? a) => null; // warn Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(3, 48) ); } [Fact] public void SpeakableInference_LambdaReturnTypeInference_WithNullabilityMismatch() { var source = @" class C { void M(C? x, C y) { var x1 = F(() => { bool b = true; if (b) return x; return y; }); _ = x1 /*T:C?*/; x1.ToString(); var x2 = F(() => { bool b = true; if (b) return y; return x; }); _ = x2 /*T:C?*/; x2.ToString(); } U F(System.Func f) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,20): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // return y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(10, 20), // (13,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(13, 9), // (18,27): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // if (b) return y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(18, 27), // (22,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(22, 9) ); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/32006")] [WorkItem(32006, "https://github.com/dotnet/roslyn/issues/32006")] public void SpeakableInference_LambdaReturnTypeInference_NonNullableTypelessOuptut() { // See https://github.com/dotnet/roslyn/issues/32006 // need to relax assertion in GetImplicitTupleLiteralConversion var source = @" class C { void M(C? c) { var x1 = F(() => { bool b = true; if (b) return (c, c); return (null, null); }); x1.ToString(); x1.Item1.ToString(); } T F(System.Func f) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // x1.Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1.Item1").WithLocation(13, 9) ); } [Fact] public void SpeakableInference_VarInference() { var source = @"class Program { void M(T t) { if (t == null) throw null!; var t2 = t; t2.ToString(); } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); // Once we have a public API, we should check that the declaration type of `t2` is `T` https://github.com/dotnet/roslyn/issues/26198 } [Fact] public void Directive_Qualifiers() { var source = @"#nullable #nullable enable #nullable disable #nullable restore #nullable safeonly #nullable yes "; var comp = CreateCompilation(source, options: TestOptions.DebugDll); comp.VerifyDiagnostics( // (1,10): error CS8637: Expected 'enable', 'disable', or 'restore' // #nullable Diagnostic(ErrorCode.ERR_NullableDirectiveQualifierExpected, "").WithLocation(1, 10), // (5,11): error CS8637: Expected 'enable', 'disable', or 'restore' // #nullable safeonly Diagnostic(ErrorCode.ERR_NullableDirectiveQualifierExpected, "safeonly").WithLocation(5, 11), // (6,11): error CS8637: Expected 'enable', 'disable', or 'restore' // #nullable yes Diagnostic(ErrorCode.ERR_NullableDirectiveQualifierExpected, "yes").WithLocation(6, 11) ); comp.VerifyTypes(); } [Fact] public void Directive_NullableDefault() { var source = @"#pragma warning disable 0649 class A { } class B { static A F1; static void G1() { object o1; o1 = F1/*T:A!*/; o1 = F2/*T:A!*/; o1 = F3/*T:A!*/; } #nullable disable static A F2; static void G2() { object o2; o2 = F1/*T:A!*/; o2 = F2/*T:A!*/; o2 = F3/*T:A!*/; } #nullable enable static A F3; static void G3() { object o3; o3 = F1/*T:A!*/; o3 = F2/*T:A!*/; o3 = F3/*T:A!*/; } }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll); comp.VerifyDiagnostics( // (5,28): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static A F1; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 28), // (14,28): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static A F2; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 28)); comp.VerifyTypes(); } [Fact] public void Directive_NullableFalse() { var source = @"#pragma warning disable 0649 class A { } class B { static A F1; static void G1() { object o1; o1 = F1/*T:A!*/; o1 = F2/*T:A!*/; o1 = F3/*T:A!*/; } #nullable disable static A F2; static void G2() { object o2; o2 = F1/*T:A!*/; o2 = F2/*T:A!*/; o2 = F3/*T:A!*/; } #nullable enable static A F3; static void G3() { object o3; o3 = F1/*T:A!*/; o3 = F2/*T:A!*/; o3 = F3/*T:A!*/; } }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Disable)); comp.VerifyDiagnostics( // (5,28): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static A F1; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 28), // (14,28): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static A F2; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 28)); comp.VerifyTypes(); } [Fact] public void Directive_NullableTrue() { var source = @"#pragma warning disable 0649 class A { } class B { static A F1; static void G1() { object o1; o1 = F1/*T:A!*/; o1 = F2/*T:A!*/; o1 = F3/*T:A!*/; } #nullable disable static A F2; static void G2() { object o2; o2 = F1/*T:A!*/; o2 = F2/*T:A!*/; o2 = F3/*T:A!*/; } #nullable enable static A F3; static void G3() { object o3; o3 = F1/*T:A!*/; o3 = F2/*T:A!*/; o3 = F3/*T:A!*/; } }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (14,28): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static A F2; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 28)); comp.VerifyTypes(); } [Fact] public void Directive_PartialClasses() { var source0 = @"class Base { } class Program { #nullable enable static void F(Base b) { } static void Main() { F(new C1()); F(new C2()); F(new C3()); F(new C4()); F(new C5()); F(new C6()); F(new C7()); F(new C8()); F(new C9()); } }"; var source1 = @"#pragma warning disable 8632 partial class C1 : Base { } partial class C2 { } partial class C3 : Base { } #nullable disable partial class C4 { } partial class C5 : Base { } partial class C6 { } #nullable enable partial class C7 : Base { } partial class C8 { } partial class C9 : Base { } "; var source2 = @"#pragma warning disable 8632 partial class C1 { } partial class C4 : Base { } partial class C7 { } #nullable disable partial class C2 : Base { } partial class C5 { } partial class C8 : Base { } #nullable enable partial class C3 { } partial class C6 : Base { } partial class C9 { } "; // -nullable (default): var comp = CreateCompilation(new[] { source0, source1, source2 }, options: TestOptions.DebugDll); comp.VerifyDiagnostics( // (15,11): warning CS8620: Nullability of reference types in argument of type 'C6' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C6()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C6()").WithArguments("C6", "Base", "b", "void Program.F(Base b)").WithLocation(15, 11), // (16,11): warning CS8620: Nullability of reference types in argument of type 'C7' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C7()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C7()").WithArguments("C7", "Base", "b", "void Program.F(Base b)").WithLocation(16, 11), // (18,11): warning CS8620: Nullability of reference types in argument of type 'C9' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C9()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C9()").WithArguments("C9", "Base", "b", "void Program.F(Base b)").WithLocation(18, 11)); // -nullable-: comp = CreateCompilation(new[] { source0, source1, source2 }, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Disable)); comp.VerifyDiagnostics( // (15,11): warning CS8620: Nullability of reference types in argument of type 'C6' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C6()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C6()").WithArguments("C6", "Base", "b", "void Program.F(Base b)").WithLocation(15, 11), // (16,11): warning CS8620: Nullability of reference types in argument of type 'C7' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C7()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C7()").WithArguments("C7", "Base", "b", "void Program.F(Base b)").WithLocation(16, 11), // (18,11): warning CS8620: Nullability of reference types in argument of type 'C9' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C9()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C9()").WithArguments("C9", "Base", "b", "void Program.F(Base b)").WithLocation(18, 11)); // -nullable+: comp = CreateCompilation(new[] { source0, source1, source2 }, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (10,11): warning CS8620: Nullability of reference types in argument of type 'C1' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C1()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C1()").WithArguments("C1", "Base", "b", "void Program.F(Base b)").WithLocation(10, 11), // (12,11): warning CS8620: Nullability of reference types in argument of type 'C3' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C3()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C3()").WithArguments("C3", "Base", "b", "void Program.F(Base b)").WithLocation(12, 11), // (13,11): warning CS8620: Nullability of reference types in argument of type 'C4' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C4()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C4()").WithArguments("C4", "Base", "b", "void Program.F(Base b)").WithLocation(13, 11), // (15,11): warning CS8620: Nullability of reference types in argument of type 'C6' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C6()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C6()").WithArguments("C6", "Base", "b", "void Program.F(Base b)").WithLocation(15, 11), // (16,11): warning CS8620: Nullability of reference types in argument of type 'C7' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C7()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C7()").WithArguments("C7", "Base", "b", "void Program.F(Base b)").WithLocation(16, 11), // (18,11): warning CS8620: Nullability of reference types in argument of type 'C9' doesn't match target type 'Base' for parameter 'b' in 'void Program.F(Base b)'. // F(new C9()); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new C9()").WithArguments("C9", "Base", "b", "void Program.F(Base b)").WithLocation(18, 11)); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void Directive_EnableAndDisable_01() { var source = @"#nullable enable class Program { static void F(object x) { object? y = null; F(y); // warning } #nullable disable static void G() { F(null); } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,11): warning CS8604: Possible null reference argument for parameter 'x' in 'void Program.F(object x)'. // F(y); // warning Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void Program.F(object x)").WithLocation(7, 11)); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void Directive_EnableAndDisable_02() { var source = @"class Program { #nullable disable static void G() { F(null); } #nullable enable static void F(object x) { object? y = null; F(y); // warning } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (12,11): warning CS8604: Possible null reference argument for parameter 'x' in 'void Program.F(object x)'. // F(y); // warning Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void Program.F(object x)").WithLocation(12, 11)); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void Directive_EnableAndDisable_03() { var source = @"class Program { static void F(object x) { object? y = null; F(y); // warning } #nullable disable static void G() { F(null); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,11): warning CS8604: Possible null reference argument for parameter 'x' in 'void Program.F(object x)'. // F(y); // warning Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void Program.F(object x)").WithLocation(6, 11)); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void Directive_EnableAndDisable_04() { var source = @"class Program { static void G() { F(null); } #nullable enable static void F(object x) { object? y = null; F(y); // warning } }"; var comp = CreateCompilation(source, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics( // (11,11): warning CS8604: Possible null reference argument for parameter 'x' in 'void Program.F(object x)'. // F(y); // warning Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void Program.F(object x)").WithLocation(11, 11)); } [Fact] public void Directive_GloballyEnabled_GeneratedCode_DisabledByDefault() { var source = @" // class Program { static void F(object x) { x = null; // no warning, generated file } }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics(); } [Fact] public void Directive_GloballyEnabled_GeneratedCode_Enabled() { var source = @" // #nullable enable class Program { static void F(object x) { x = null; // warning } }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; // warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 13) ); } [Fact] public void Directive_GloballyEnabled_GeneratedCode_RestoreToProjectDefault() { var source = @" // partial class Program { #nullable restore static void F(object x) { x = null; // warning, restored to project default } }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; // warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 13) ); } [Fact] public void Directive_GloballyEnabled_GeneratedCode_WarningsAreDisabledByDefault() { var source = @" // partial class Program { static void G(object x) { x = null; // no warning F = null; // no warning #nullable enable warnings x = null; // no warning - declared out of nullable context F = null; // warning - declared in a nullable context } #nullable enable static object F = new object(); }"; var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (12,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // warning - declared in a nullable context Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 13) ); } [Fact] public void Directive_GloballyEnabled_GeneratedCode_PartialClasses() { var source1 = @" // partial class Program { static void G(object x) { x = null; // no warning F = null; // no warning } }"; var source2 = @" partial class Program { static object F = new object(); static void H() { F = null; // warning } }"; var comp = CreateCompilation(new[] { source1, source2 }, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (8,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // warning Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 13) ); } [Fact] public void Directive_GloballyEnabled_GeneratedCode_PartialClasses2() { var source1 = @" // partial class Program { #nullable enable warnings static void G(object x) { x = null; // no warning F = null; // warning } }"; var source2 = @" partial class Program { static object F = new object(); static void H() { F = null; // warning } }"; var comp = CreateCompilation(new[] { source1, source2 }, options: TestOptions.DebugDll.WithNullableContextOptions(NullableContextOptions.Enable)); comp.VerifyDiagnostics( // (8,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // warning Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 13), // (9,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // warning Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(9, 13) ); } [WorkItem(30862, "https://github.com/dotnet/roslyn/issues/30862")] [Fact] public void DirectiveDisableWarningEnable() { var source = @"#nullable enable class Program { static void F(object x) { } #nullable disable static void F1(object? y, object? z) { F(y); #pragma warning restore 8604 F(z); // 1 } static void F2(object? w) { F(w); // 2 } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void F1(object? y, object? z) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 26), // (8,37): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void F1(object? y, object? z) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 37), // (14,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void F2(object? w) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 26)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void PragmaNullable_NoEffect() { var source = @" #pragma warning disable nullable class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_Enable_01() { var source = @" #nullable enable annotations class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_Enable_02() { var source = @" #nullable enable #nullable disable warnings class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_Enable_03() { var source = @" #nullable enable #nullable restore warnings class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_Enable_04() { var source = @" class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypes(NullableContextOptions.Annotations)); comp.VerifyDiagnostics(); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_Enable_05() { var source = @" #nullable enable #nullable restore warnings class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics(); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_Enable_06() { var source = @" #nullable disable #nullable restore warnings class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // static void M(string? s) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 25), // (8,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_NonFlowAnalysisWarning_01() { var source = @" #nullable enable annotations public partial class C { partial void M(string? s); } public partial class C { partial void M(string s) { } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,18): warning CS8611: Nullability of reference types in type of parameter 's' doesn't match partial method declaration. // partial void M(string s) { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M").WithArguments("s").WithLocation(10, 18)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_NonFlowAnalysisWarning_02() { var source = @" using System.Collections.Generic; #nullable enable annotations class Base { internal virtual void M(List list) { } } class Derived : Base { internal override void M(List list) { } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (11,28): warning CS8610: Nullability of reference types in type of parameter 'list' doesn't match overridden member. // internal override void M(List list) { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M").WithArguments("list").WithLocation(11, 28)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Annotations_NonFlowAnalysisWarning_03() { var source = @" using System.Collections.Generic; class Base { internal virtual void M(List list) { } } #nullable enable annotations class Derived : Base { // No warning because the base method's parameter type is oblivious internal override void M(List list) { } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Warnings_Enable_01() { var source = @" #nullable enable warnings class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (5,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // static void M(string? s) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 25), // (7,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Warnings_Enable_02() { var source = @" #nullable enable #nullable disable annotations class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // static void M(string? s) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 25), // (8,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Warnings_Enable_03() { var source = @" #nullable enable #nullable restore annotations class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // static void M(string? s) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 25), // (8,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Warnings_Enable_04() { var source = @" class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypes(NullableContextOptions.Warnings)); comp.VerifyDiagnostics( // (4,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // static void M(string? s) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 25), // (6,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Warnings_Enable_05() { var source = @" #nullable enable #nullable restore annotations class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics( // (6,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // static void M(string? s) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 25), // (8,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13)); } [Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")] public void Directive_Warnings_Enable_06() { var source = @" #nullable disable #nullable restore annotations class Program { static void M(string? s) { _ = s.ToString(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(35730, "https://github.com/dotnet/roslyn/issues/35730")] public void Directive_ProjectNoWarn() { var source = @" #nullable enable class Program { void M1(string? s) { _ = s.ToString(); } } "; var comp1 = CreateCompilation(source); comp1.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // _ = s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13)); var id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullReferenceReceiver); var comp2 = CreateCompilation(source, options: TestOptions.DebugDll.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress)); comp2.VerifyDiagnostics(); } [Fact, WorkItem(31740, "https://github.com/dotnet/roslyn/issues/31740")] public void Attribute_ArrayWithDifferentNullability() { var source = @" public class MyAttribute : System.Attribute { public MyAttribute(string[] x) { } } #nullable enable [My(new string[] { ""hello"" })] class C { } "; var comp = CreateCompilation(source, options: TestOptions.DebugDll); comp.VerifyDiagnostics(); } [Fact, WorkItem(31740, "https://github.com/dotnet/roslyn/issues/31740")] public void Attribute_ArrayWithDifferentNullability2() { var source = @" public class MyAttribute : System.Attribute { public MyAttribute(string[] x) { } } #nullable enable [My(new string[] { null })] class C { } "; var comp = CreateCompilation(source, options: TestOptions.DebugDll); comp.VerifyDiagnostics( // (7,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [My(new string[] { null })] Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 20) ); } [Fact, WorkItem(31740, "https://github.com/dotnet/roslyn/issues/31740")] public void Attribute_ArrayWithDifferentNullability_DynamicAndTupleNames() { var source = @" public class MyAttribute : System.Attribute { public MyAttribute((string alice, string)[] x, dynamic[] y, object[] z) { } } #nullable enable [My(new (string, string bob)[] { }, new object[] { }, new dynamic[] { })] class C { } "; var comp = CreateCompilation(source, options: TestOptions.DebugDll); comp.VerifyDiagnostics( // (7,2): error CS0181: Attribute constructor parameter 'x' has type '(string alice, string)[]', which is not a valid attribute parameter type // [My(new (string, string bob)[] { }, new object[] { }, new dynamic[] { })] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "My").WithArguments("x", "(string alice, string)[]").WithLocation(7, 2), // (7,2): error CS0181: Attribute constructor parameter 'y' has type 'dynamic[]', which is not a valid attribute parameter type // [My(new (string, string bob)[] { }, new object[] { }, new dynamic[] { })] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "My").WithArguments("y", "dynamic[]").WithLocation(7, 2) ); } [Fact, WorkItem(31740, "https://github.com/dotnet/roslyn/issues/31740")] public void Attribute_ArrayWithDifferentNullability_Dynamic() { var source = @" public class MyAttribute : System.Attribute { public MyAttribute(dynamic[] y) { } } #nullable enable [My(new object[] { })] class C { } "; var comp = CreateCompilation(source, options: TestOptions.DebugDll); comp.VerifyDiagnostics( // (7,2): error CS0181: Attribute constructor parameter 'y' has type 'dynamic[]', which is not a valid attribute parameter type // [My(new object[] { })] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "My").WithArguments("y", "dynamic[]").WithLocation(7, 2) ); } [Fact] public void AttributeArgument_Constructor_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s) { } } [MyAttribute(null)] //1 class C { } [MyAttribute(""str"")] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14) ); } [Fact] public void AttributeArgument_Constructor_NullLiteral_Suppressed() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s) { } } [MyAttribute(null!)] class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact] public void AttributeArgument_Constructor_NullLiteral_CSharp7_3() { var source = @" class MyAttribute : System.Attribute { public MyAttribute(string s) { } } [MyAttribute(null)] class C { } [MyAttribute(""str"")] class D { } "; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(); } [Fact] public void AttributeArgument_Constructor_NullLiteral_WithDefaultArgument() { var source = @"#nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s, string s2 = ""str"") { } } [MyAttribute(null)] //1 class C { } [MyAttribute(null, null)] // 2, 3 class D { } [MyAttribute(null, ""str"")] // 4 class E { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 14), // (10,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, null)] // 2, 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 14), // (10,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, null)] // 2, 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 20), // (13,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, "str")] // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 14) ); } [Fact] public void AttributeArgument_Constructor_NullLiteral_WithNullDefaultArgument() { var source = @"#nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s, string s2 = null) { } //1 } [MyAttribute(""str"")] class C { } [MyAttribute(""str"", null)] // 2 class D { } [MyAttribute(""str"", ""str"")] class E { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (4,46): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // public MyAttribute(string s, string s2 = null) { } //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 46), // (10,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("str", null)] // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 21) ); } [Fact] public void AttributeArgument_Constructor_NullLiteral_WithNamedArguments() { var source = @"#nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s, string s2 = ""str"", string? s3 = ""str"") { } } [MyAttribute(""str"", s2: null, s3: null)] //1 class C { } [MyAttribute(s3: null, s2: null, s: ""str"")] // 2 class D { } [MyAttribute(s3: null, s2: ""str"", s: ""str"")] class E { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,25): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("str", s2: null, s3: null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 25), // (10,28): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(s3: null, s2: null, s: "str")] // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 28) ); } [Fact] public void AttributeArgument_Constructor_NullLiteral_DisabledEnabled() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s, string s2) { } } [MyAttribute(null, //1 #nullable disable null #nullable enable )] class C { } [MyAttribute( #nullable disable null, #nullable enable null //2 )] class D { } [MyAttribute(null, //3 s2: #nullable disable null #nullable enable )] class E { } [MyAttribute( #nullable disable null, s2: #nullable enable null //4 )] class F { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14), // (19,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // null //2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 1), // (23,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, //3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(23, 14), // (36,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // null //4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(36, 1) ); } [Fact] public void AttributeArgument_Constructor_NullLiteral_WarningDisabledEnabled() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s, string s2) { } } #nullable disable #nullable enable warnings [MyAttribute(null, //1 #nullable disable warnings null #nullable enable warnings )] class C { } [MyAttribute( #nullable disable warnings null, #nullable enable warnings null //2 )] class D { } [MyAttribute(null, //3 s2: #nullable disable warnings null #nullable enable warnings )] class E { } [MyAttribute( #nullable disable warnings null, s2: #nullable enable warnings null //4 )] class F { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 14), // (21,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // null //2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(21, 1), // (25,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, //3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(25, 14), // (38,1): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // null //4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(38, 1) ); } [Fact] public void AttributeArgument_Constructor_Array_LiteralNull() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string[] s) { } } [MyAttribute(null)] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14) ); } [Fact] public void AttributeArgument_Constructor_Array_LiteralNull_Suppressed() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string[] s) { } } [MyAttribute(null!)] class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact] public void AttributeArgument_Constructor_Array_ArrayOfNullable() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string[] s) { } } [MyAttribute(new string?[]{ null })] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,14): warning CS8620: Argument of type 'string?[]' cannot be used as an input of type 'string[]' for parameter 's' in 'MyAttribute.MyAttribute(string[] s)' due to differences in the nullability of reference types. // [MyAttribute(new string?[]{ null })] //1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new string?[]{ null }").WithArguments("string?[]", "string[]", "s", "MyAttribute.MyAttribute(string[] s)").WithLocation(8, 14) ); } [Fact] public void AttributeArgument_Constructor_Array_ArrayOfNullable_Suppressed() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string[] s) { } } [MyAttribute(new string?[]{ null }!)] class C { } [MyAttribute(new string[]{ null! })] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact] public void AttributeArgument_Constructor_Array_ArrayOfNullable_ImplicitType() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string[] s) { } } [MyAttribute(new []{ ""str"", null })] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,14): warning CS8620: Argument of type 'string?[]' cannot be used as an input of type 'string[]' for parameter 's' in 'MyAttribute.MyAttribute(string[] s)' due to differences in the nullability of reference types. // [MyAttribute(new []{ "str", null })] //1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, @"new []{ ""str"", null }").WithArguments("string?[]", "string[]", "s", "MyAttribute.MyAttribute(string[] s)").WithLocation(8, 14) ); } [Fact] public void AttributeArgument_Constructor_Array_NullValueInInitializer() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string[] s) { } } [MyAttribute(new string[]{ ""str"", null, ""str"" })] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,35): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(new string[]{ "str", null, "str" })] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 35) ); } [Fact] public void AttributeArgument_Constructor_Array_NullValueInNestedInitializer() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(object[] s) { } } [MyAttribute(new object[] { new string[] { ""str"", null }, //1 new string[] { null }, //2 new string?[] { null } })] class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,27): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // new string[] { "str", null }, //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 27), // (11,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // new string[] { null }, //2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 20) ); } [Fact] public void AttributeArgument_Constructor_ParamsArrayOfNullable_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(params object?[] s) { } } [MyAttribute(null)] //1 class C { } [MyAttribute(null, null)] class D { } [MyAttribute((object?)null)] class E { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 14) ); } [Fact] public void AttributeArgument_Constructor_ParamsArray_NullItem() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute(string s1, params object[] s) { } } [MyAttribute(""str"", null, ""str"", ""str"")] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (8,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("str", null, "str", "str")] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 21) ); } [Fact] public void AttributeArgument_PropertyAssignment_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute() { } public string MyValue { get; set; } = ""str""; } [MyAttribute(MyValue = null)] //1 class C { } [MyAttribute(MyValue = ""str"")] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(MyValue = null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 24) ); } [Fact] public void AttributeArgument_PropertyAssignment_Array_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute() { } public string[] PropertyArray { get; set; } = new string[] { }; public string[]? NullablePropertyArray { get; set; } = null; } [MyAttribute(PropertyArray = null)] //1 class C { } [MyAttribute(NullablePropertyArray = null)] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (13,30): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(PropertyArray = null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 30) ); } [Fact] public void AttributeArgument_PropertyAssignment_Array_ArrayOfNullable() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute() { } public string[] PropertyArray { get; set; } = new string[] { ""str"" }; public string[]? PropertyNullableArray { get; set; } = new string[] { ""str"" }; } [MyAttribute(PropertyArray = new string?[]{ null })] //1 class C { } [MyAttribute(PropertyNullableArray = null)] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (12,30): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'. // [MyAttribute(PropertyArray = new string?[]{ null })] //1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(12, 30) ); } [Fact] public void AttributeArgument_FieldAssignment_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute() { } public string myValue = ""str""; } [MyAttribute(myValue = null)] //1 class C { } [MyAttribute(myValue = ""str"")] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(myValue = null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 24) ); } [Fact] public void AttributeArgument_FieldAssignment_Array_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute() { } public string[] fieldArray = new string[] { }; public string[]? nullableFieldArray = null; } [MyAttribute(fieldArray = null)] //1 class C { } [MyAttribute(nullableFieldArray = null)] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (12,27): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(fieldArray = null)] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 27) ); } [Fact] public void AttributeArgument_FieldAssignment_Array_ArrayOfNullable() { var source = @" #nullable enable class MyAttribute : System.Attribute { public MyAttribute() { } public string[] fieldArray = new string[] { }; public string?[] fieldArrayOfNullable = new string?[] { }; } [MyAttribute(fieldArray = new string?[]{ null })] //1 class C { } [MyAttribute(fieldArrayOfNullable = new string?[]{ null })] class D { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (12,27): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'. // [MyAttribute(fieldArray = new string?[]{ null })] //1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(12, 27) ); } [Fact] public void AttributeArgument_NoMatchingConstructor_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { } [MyAttribute(null)] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments // [MyAttribute(null)] //1 Diagnostic(ErrorCode.ERR_BadCtorArgCount, "MyAttribute(null)").WithArguments("MyAttribute", "1").WithLocation(7, 2) ); } [Fact] public void AttributeArgument_NoMatchingConstructor_Array_NullValueInInitializer() { var source = @" #nullable enable class MyAttribute : System.Attribute { } [MyAttribute(new string[] { null })] //1 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments // [MyAttribute(new string[] { null })] //1 Diagnostic(ErrorCode.ERR_BadCtorArgCount, "MyAttribute(new string[] { null })").WithArguments("MyAttribute", "1").WithLocation(7, 2), // (7,29): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(new string[] { null })] //1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 29) ); } [Fact] public void AttributeArgument_NoMatchingConstructor_PropertyAssignment_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public string[] PropertyArray { get; set; } = new string[] { ""str"" }; public string[]? PropertyNullableArray { get; set; } = new string[] { ""str"" }; } [MyAttribute( // 1 new string[] { null }, // 2 PropertyArray = null, // 3 PropertyNullableArray = new string[] { null } // 4 )] class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments // [MyAttribute( // 1 Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"MyAttribute( // 1 new string[] { null }, // 2 PropertyArray = null, // 3 PropertyNullableArray = new string[] { null } // 4 )").WithArguments("MyAttribute", "1").WithLocation(10, 2), // (11,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // new string[] { null }, // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 20), // (12,21): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // PropertyArray = null, // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 21), // (13,44): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // PropertyNullableArray = new string[] { null } // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 44) ); } [Fact] public void AttributeArgument_NoMatchingConstructor_FieldAssignment_NullLiteral() { var source = @" #nullable enable class MyAttribute : System.Attribute { public string[] fieldArray = new string[] { }; public string?[] fieldArrayOfNullable = new string?[] { }; } [MyAttribute( // 1 new string[] { null }, // 2 fieldArray = null, // 3 fieldArrayOfNullable = new string[] { null } // 4 )] class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,2): error CS1729: 'MyAttribute' does not contain a constructor that takes 1 arguments // [MyAttribute( // 1 Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"MyAttribute( // 1 new string[] { null }, // 2 fieldArray = null, // 3 fieldArrayOfNullable = new string[] { null } // 4 )").WithArguments("MyAttribute", "1").WithLocation(10, 2), // (11,20): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // new string[] { null }, // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 20), // (12,18): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // fieldArray = null, // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 18), // (13,43): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // fieldArrayOfNullable = new string[] { null } // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 43) ); } [Fact] public void AttributeArgument_ComplexAssignment() { var source = @" #nullable enable [System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = true)] class MyAttribute : System.Attribute { public MyAttribute(string s, string s2 = ""str"", string s3 = ""str"") { } public string[] fieldArray = new string[] { }; public string?[] fieldArrayOfNullable = new string[] { }; public string[]? nullableFieldArray = null; public string[] PropertyArray { get; set; } = new string[] { }; public string?[] PropertyArrayOfNullable { get; set; } = new string[] { }; public string[]? NullablePropertyArray { get; set; } = null; } [MyAttribute(""s1"")] [MyAttribute(""s1"", s3: ""s3"", fieldArray = new string[]{})] [MyAttribute(""s1"", s2: ""s2"", fieldArray = new string[]{}, PropertyArray = new string[]{})] [MyAttribute(""s1"", fieldArrayOfNullable = new string?[]{ null }, NullablePropertyArray = null)] [MyAttribute(null)] // 1 [MyAttribute(""s1"", s3: null, fieldArray = new string[]{})] // 2 [MyAttribute(""s1"", s2: ""s2"", fieldArray = new string?[]{ null }, PropertyArray = new string[]{})] // 3 [MyAttribute(""s1"", PropertyArrayOfNullable = null)] // 4 [MyAttribute(""s1"", NullablePropertyArray = new string?[]{ null })] // 5 [MyAttribute(""s1"", fieldArrayOfNullable = null)] // 6 [MyAttribute(""s1"", nullableFieldArray = new string[]{ null })] // 7 [MyAttribute(null, //8 s2: null, //9 fieldArrayOfNullable = null, //10 NullablePropertyArray = new string?[]{ null })] // 11 [MyAttribute(null, // 12 #nullable disable s2: null, #nullable enable fieldArrayOfNullable = null, //13 #nullable disable warnings NullablePropertyArray = new string?[]{ null }, #nullable enable warnings nullableFieldArray = new string?[]{ null })] //14 class C { } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (26,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null)] // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(26, 14), // (27,24): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("s1", s3: null, fieldArray = new string[]{})] // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(27, 24), // (28,43): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'. // [MyAttribute("s1", s2: "s2", fieldArray = new string?[]{ null }, PropertyArray = new string[]{})] // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(28, 43), // (29,46): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("s1", PropertyArrayOfNullable = null)] // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(29, 46), // (30,44): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'. // [MyAttribute("s1", NullablePropertyArray = new string?[]{ null })] // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(30, 44), // (31,43): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("s1", fieldArrayOfNullable = null)] // 6 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(31, 43), // (32,55): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute("s1", nullableFieldArray = new string[]{ null })] // 7 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(32, 55), // (33,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, //8 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(33, 14), // (34,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // s2: null, //9 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(34, 17), // (35,36): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // fieldArrayOfNullable = null, //10 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(35, 36), // (36,37): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'. // NullablePropertyArray = new string?[]{ null })] // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(36, 37), // (37,14): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // [MyAttribute(null, // 12 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(37, 14), // (41,36): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // fieldArrayOfNullable = null, //13 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(41, 36), // (45,34): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'string[]'. // nullableFieldArray = new string?[]{ null })] //14 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new string?[]{ null }").WithArguments("string?[]", "string[]").WithLocation(45, 34) ); } [Fact] public void NullableAndConditionalOperators() { var source = @"class Program { static void F1(object x) { _ = x is string? 1 : 2; _ = x is string? ? 1 : 2; // error 1: is a nullable reference type _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type _ = x as string?? x; _ = x as string ? ?? x; // error 3: as a nullable reference type } static void F2(object y) { _ = y is object[]? 1 : 2; _ = y is object[]? ? 1 : 2; // error 4 _ = y is object[] ? ? 1 : 2; // error 5 _ = y as object[]?? y; _ = y as object[] ? ?? y; // error 6 } static void F3(object z) { _ = z is T[][]? 1 : 2; _ = z is T[]?[] ? 1 : 2; _ = z is T[] ? [] ? 1 : 2; _ = z as T[][]?? z; _ = z as T[] ? [] ?? z; } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics( // (6,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. // _ = x is string? ? 1 : 2; // error 1: is a nullable reference type Diagnostic(ErrorCode.ERR_IsNullableType, "string?").WithArguments("string").WithLocation(6, 18), // (6,24): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = x is string? ? 1 : 2; // error 1: is a nullable reference type Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(6, 24), // (7,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. // _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type Diagnostic(ErrorCode.ERR_IsNullableType, "string ?").WithArguments("string").WithLocation(7, 18), // (7,25): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(7, 25), // (9,18): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // _ = x as string ? ?? x; // error 3: as a nullable reference type Diagnostic(ErrorCode.ERR_AsNullableType, "string ?").WithArguments("string").WithLocation(9, 18), // (9,25): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = x as string ? ?? x; // error 3: as a nullable reference type Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(9, 25), // (14,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. // _ = y is object[]? ? 1 : 2; // error 4 Diagnostic(ErrorCode.ERR_IsNullableType, "object[]?").WithArguments("object[]").WithLocation(14, 18), // (14,26): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = y is object[]? ? 1 : 2; // error 4 Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(14, 26), // (15,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. // _ = y is object[] ? ? 1 : 2; // error 5 Diagnostic(ErrorCode.ERR_IsNullableType, "object[] ?").WithArguments("object[]").WithLocation(15, 18), // (15,27): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = y is object[] ? ? 1 : 2; // error 5 Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(15, 27), // (17,18): error CS8651: It is not legal to use nullable reference type 'object[]?' in an as expression; use the underlying type 'object[]' instead. // _ = y as object[] ? ?? y; // error 6 Diagnostic(ErrorCode.ERR_AsNullableType, "object[] ?").WithArguments("object[]").WithLocation(17, 18), // (17,27): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = y as object[] ? ?? y; // error 6 Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(17, 27), // (22,21): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = z is T[]?[] ? 1 : 2; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(22, 21), // (23,22): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = z is T[] ? [] ? 1 : 2; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(23, 22), // (25,22): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = z as T[] ? [] ?? z; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(25, 22) ); comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. // _ = x is string? ? 1 : 2; // error 1: is a nullable reference type Diagnostic(ErrorCode.ERR_IsNullableType, "string?").WithArguments("string").WithLocation(6, 18), // (7,18): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead. // _ = x is string ? ? 1 : 2; // error 2: is a nullable reference type Diagnostic(ErrorCode.ERR_IsNullableType, "string ?").WithArguments("string").WithLocation(7, 18), // (9,18): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // _ = x as string ? ?? x; // error 3: as a nullable reference type Diagnostic(ErrorCode.ERR_AsNullableType, "string ?").WithArguments("string").WithLocation(9, 18), // (14,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. // _ = y is object[]? ? 1 : 2; // error 4 Diagnostic(ErrorCode.ERR_IsNullableType, "object[]?").WithArguments("object[]").WithLocation(14, 18), // (15,18): error CS8650: It is not legal to use nullable reference type 'object[]?' in an is-type expression; use the underlying type 'object[]' instead. // _ = y is object[] ? ? 1 : 2; // error 5 Diagnostic(ErrorCode.ERR_IsNullableType, "object[] ?").WithArguments("object[]").WithLocation(15, 18), // (17,18): error CS8651: It is not legal to use nullable reference type 'object[]?' in an as expression; use the underlying type 'object[]' instead. // _ = y as object[] ? ?? y; // error 6 Diagnostic(ErrorCode.ERR_AsNullableType, "object[] ?").WithArguments("object[]").WithLocation(17, 18) ); } [Fact, WorkItem(29318, "https://github.com/dotnet/roslyn/issues/29318")] public void IsOperatorOnNonNullExpression() { var source = @" class C { void M(object o) { if (o is string) { o.ToString(); } else { o.ToString(); } } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); c.VerifyDiagnostics(); } [Fact, WorkItem(29318, "https://github.com/dotnet/roslyn/issues/29318")] public void IsOperatorOnMaybeNullExpression() { var source = @" class C { static void Main(object? o) { if (o is string) { o.ToString(); } else { o.ToString(); // 1 } } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(12, 13) ); } [Fact, WorkItem(29318, "https://github.com/dotnet/roslyn/issues/29318")] public void IsOperatorOnUnconstrainedType() { var source = @" class C { static void M(T t) { if (t is string) { t.ToString(); } else { t.ToString(); // 1 } } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(12, 13) ); } [Fact] public void IsOperator_AffectsNullConditionalOperator() { var source = @" class C { public object? field = null; static void M(C? c) { if (c?.field is string) { c.ToString(); c.field.ToString(); } else { c.ToString(); // 1 } } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (14,13): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(14, 13) ); } [Fact] public void OmittedCall() { var source = @" partial class C { void M(string? x) { OmittedMethod(x); } partial void OmittedMethod(string x); } "; var c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,23): warning CS8604: Possible null reference argument for parameter 'x' in 'void C.OmittedMethod(string x)'. // OmittedMethod(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void C.OmittedMethod(string x)").WithLocation(6, 23) ); } [Fact] public void OmittedInitializerCall() { var source = @" using System.Collections; partial class Collection : IEnumerable { void M(string? x) { _ = new Collection() { x }; } IEnumerator IEnumerable.GetEnumerator() => throw null!; partial void Add(string x); } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,32): warning CS8604: Possible null reference argument for parameter 'x' in 'void Collection.Add(string x)'. // _ = new Collection() { x }; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void Collection.Add(string x)").WithLocation(7, 32) ); } [Fact] public void UpdateArrayRankSpecifier() { var source = @" class C { static void Main() { object[]? x = null; } } "; var tree = Parse(source); var specifier = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("[]", specifier.ToString()); var newSpecifier = specifier.Update( specifier.OpenBracketToken, SyntaxFactory.SeparatedList( new[] { SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(3)) }), specifier.CloseBracketToken); Assert.Equal("[3]", newSpecifier.ToString()); } [Fact] public void TestUnaryNegation() { // This test verifies that we no longer crash hitting an assertion var source = @" public class C { C(C c) => throw null!; void M(bool b) { _ = new C(!b); } public static implicit operator C(T x) => throw null!; } "; var c = CreateCompilation(source, parseOptions: TestOptions.Regular8); c.VerifyDiagnostics(); } [Fact] public void UnconstrainedAndErrorNullableFields() { var source = @" public class C { public T? field; public Unknown? field2; } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (5,12): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // public Unknown? field2; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(5, 12), // (4,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public T? field; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 12), // (4,15): warning CS8618: Non-nullable field 'field' is uninitialized. // public T? field; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "field").WithArguments("field", "field").WithLocation(4, 15)); } [Fact] public void NoNullableAnalysisWithoutNonNullTypes() { var source = @" class C { void M(string z) { z = null; z.ToString(); } } #nullable enable class C2 { void M(string z) { z = null; // 1 z.ToString(); // 2 } } "; var expected = new[] { // (15,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // z = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(15, 13), // (16,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(16, 9) }; var c = CreateCompilation(new[] { source }); c.VerifyDiagnostics(expected); c = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); c.VerifyDiagnostics(expected); expected = new[] { // (10,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(10, 2) }; var c2 = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); c2.VerifyDiagnostics(expected); var c3 = CreateCompilation(source, parseOptions: TestOptions.RegularDefault, skipUsesIsNullable: true); c3.VerifyDiagnostics(expected); } [Fact] public void NonNullTypesOnPartialSymbol() { var source = @" #nullable enable partial class C { #nullable disable partial void M(); } #nullable enable partial class C { #nullable disable partial void M() { } } "; var c = CreateCompilation(new[] { source }); c.VerifyDiagnostics( ); } [Fact] public void SuppressionAsLValue() { var source = @" class C { void M(string? x) { ref string y = ref x; ref string y2 = ref x; (y2! = ref y) = ref y; } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,28): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // ref string y = ref x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("string?", "string").WithLocation(6, 28), // (7,29): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // ref string y2 = ref x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("string?", "string").WithLocation(7, 29), // (8,10): error CS8598: The suppression operator is not allowed in this context // (y2! = ref y) = ref y; Diagnostic(ErrorCode.ERR_IllegalSuppression, "y2").WithLocation(8, 10), // (8,20): warning CS8601: Possible null reference assignment. // (y2! = ref y) = ref y; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(8, 20), // (8,29): warning CS8601: Possible null reference assignment. // (y2! = ref y) = ref y; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(8, 29) ); } [Fact] [WorkItem(31732, "https://github.com/dotnet/roslyn/issues/31732")] public void SuppressionOnUnconstrainedTypeParameter() { var source = @" class C { void M(T t) { t!.ToString(); t.ToString(); } } "; var c = CreateCompilation(new[] { source }); c.VerifyDiagnostics(); c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(31732, "https://github.com/dotnet/roslyn/issues/31732")] public void SuppressionOnNullableValueType() { var source = @" class C { void M(int? i) { i!!.Value.ToString(); // intentional double ! i.Value.ToString(); } } "; var c = CreateCompilation(new[] { source }); c.VerifyDiagnostics(); c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(31732, "https://github.com/dotnet/roslyn/issues/31732")] public void SuppressionOnNullableValueType_AppliedOnField() { var source = @" public struct S { public string? field; } class C { void M(S? s) { s.Value.field!.ToString(); } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,9): warning CS8629: Nullable value type may be null. // s.Value.field!.ToString(); Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(10, 9) ); } [Fact] [WorkItem(31732, "https://github.com/dotnet/roslyn/issues/31732")] public void SuppressionOnNullableReferenceType_AppliedOnField() { var source = @" public class C { public string? field; void M(C? c) { c.field!.ToString(); } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // c.field!.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(7, 9) ); } [Fact] [WorkItem(31732, "https://github.com/dotnet/roslyn/issues/31732")] public void SuppressionOnNullableReferenceType_AppliedOnField2() { var source = @" public class C { public string? field; void M(C? c) { c?.field!.ToString(); c.ToString(); // We learned from suppressed dereference that `c` isn't null } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(31732, "https://github.com/dotnet/roslyn/issues/31732")] public void SuppressionOnArgument() { var source = @" class C { void M(string? s) { NonNull(s!); s.ToString(); // warn } void NonNull(string s) => throw null!; } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void SuppressionWithoutNonNullTypes() { var source = @" [System.Obsolete("""", true!)] // 1, 2 class C { string x = null!; // 3, 4 static void Main(string z = null!) // 5 { string y = null!; // 6, 7 } } "; var c = CreateCompilation(source); c.VerifyEmitDiagnostics( // (8,16): warning CS0219: The variable 'y' is assigned but its value is never used // string y = null!; // 6, 7 Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y").WithLocation(8, 16), // (5,12): warning CS0414: The field 'C.x' is assigned but its value is never used // string x = null!; // 3, 4 Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "x").WithArguments("C.x").WithLocation(5, 12) ); } [Fact, WorkItem(26812, "https://github.com/dotnet/roslyn/issues/26812")] public void DoubleAssignment() { CSharpCompilation c = CreateCompilation(new[] { @" using static System.Console; class C { static void Main() { string? x; x = x = """"; WriteLine(x.Length); string? y; x = y = """"; WriteLine(x.Length); WriteLine(y.Length); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact, WorkItem(26746, "https://github.com/dotnet/roslyn/issues/26746")] public void TernaryWithConversionFromExpression() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void M() { uint a = 0; uint x = true ? a : 1; uint y = true ? 1 : a; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact, WorkItem(26746, "https://github.com/dotnet/roslyn/issues/26746")] public void TernaryWithImplicitUsedDefinedConversion_ConstantTrue() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void M() { C c = new C(); C x = true ? c : 1; C y = true ? 1 : c; } public static implicit operator C?(int i) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // C y = true ? 1 : c; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "true ? 1 : c").WithLocation(8, 15) ); } [Fact, WorkItem(26746, "https://github.com/dotnet/roslyn/issues/26746")] public void TernaryWithImplicitUsedDefinedConversion_ConstantFalse() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void M() { C c = new C(); C x = false ? c : 1; C y = false ? 1 : c; } public static implicit operator C?(int i) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // C x = false ? c : 1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "false ? c : 1").WithLocation(7, 15) ); } [Fact, WorkItem(26746, "https://github.com/dotnet/roslyn/issues/26746")] public void TernaryWithImplicitUsedDefinedConversion_NotConstant() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void M(bool b) { C c = new C(); C x = b ? c : 1; C y = b ? 1 : c; } public static implicit operator C?(int i) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // C x = b ? c : 1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b ? c : 1").WithLocation(7, 15), // (8,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // C y = b ? 1 : c; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b ? 1 : c").WithLocation(8, 15) ); } [Fact, WorkItem(26746, "https://github.com/dotnet/roslyn/issues/26746")] public void TernaryWithImplicitUsedDefinedConversion2() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void M() { C c = null!; int x = true ? c : 1; int y = true ? 1 : c; C? c2 = null; int x2 = true ? c2 : 1; int y2 = true ? 1 : c2; } public static implicit operator int(C i) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,25): warning CS8604: Possible null reference argument for parameter 'i' in 'C.implicit operator int(C i)'. // int x2 = true ? c2 : 1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "c2").WithArguments("i", "C.implicit operator int(C i)").WithLocation(11, 25) ); } [Fact] public void AnnotationWithoutNonNullTypes() { var source = @" class C where T : class { static string? field = M2(out string? x1); // warn 1 and 2 static string? P // warn 3 { get { string? x2 = null; // warn 4 return x2; } } static string? MethodWithLocalFunction() // warn 5 { string? x3 = local(null); // warn 6 return x3; string? local(C? x) // warn 7, 8 and 9 { string? x4 = null; // warn 10 return x4; } } static string? Lambda() // warn 11 { System.Func x5 = (string? x) => // warn 12, 13 and 14 { string? x6 = null; // warn 15 return x6; }; return x5(null); } static string M2(out string? x4) => throw null!; // warn 16 static string M3(C x, C y) => throw null!; // warn 17 delegate string? MyDelegate(C x); // warn 18 and 19 event MyDelegate? Event; // warn 20 void M4() { Event(new C()); } // warn 21 class D where T2 : T? { } // warn 22 class D2 : C { } // warn 23 public static C operator +(C x, C y) => throw null!; // warn 24 and 25 class D3 { D3(C x) => throw null!; // warn 26 } public string? this[C x] { get => throw null!; } // warn 27 and 28 } "; var expectedDiagnostics = new[] { // (36,21): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // event MyDelegate? Event; // warn 20 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(36, 21), // (5,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string? P // warn 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 18), // (13,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string? MethodWithLocalFunction() // warn 5 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 18), // (24,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string? Lambda() // warn 11 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(24, 18), // (33,32): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string M2(out string? x4) => throw null!; // warn 16 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(33, 32), // (34,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string M3(C x, C y) => throw null!; // warn 17 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(34, 30), // (40,47): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static C operator +(C x, C y) => throw null!; // warn 24 and 25 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(40, 47), // (40,46): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static C operator +(C x, C y) => throw null!; // warn 24 and 25 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(40, 46), // (40,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static C operator +(C x, C y) => throw null!; // warn 24 and 25 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(40, 22), // (40,21): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static C operator +(C x, C y) => throw null!; // warn 24 and 25 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(40, 21), // (45,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public string? this[C x] { get => throw null!; } // warn 27 and 28 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(45, 33), // (45,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public string? this[C x] { get => throw null!; } // warn 27 and 28 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(45, 18), // (4,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string? field = M2(out string? x1); // warn 1 and 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 18), // (43,15): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // D3(C x) => throw null!; // warn 26 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(43, 15), // (43,14): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // D3(C x) => throw null!; // warn 26 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(43, 14), // (35,20): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // delegate string? MyDelegate(C x); // warn 18 and 19 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(35, 20), // (35,41): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // delegate string? MyDelegate(C x); // warn 18 and 19 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(35, 41), // (38,29): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class D where T2 : T? { } // warn 22 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(38, 29), // (38,28): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class D where T2 : T? { } // warn 22 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(38, 28), // (39,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class D2 : C { } // warn 23 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(39, 24), // (4,41): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static string? field = M2(out string? x1); // warn 1 and 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 41), // (9,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? x2 = null; // warn 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 19), // (15,15): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? x3 = local(null); // warn 6 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 15), // (20,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? x4 = null; // warn 10 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(20, 19), // (18,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? local(C? x) // warn 7, 8 and 9 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 31), // (18,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? local(C? x) // warn 7, 8 and 9 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 33), // (18,15): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? local(C? x) // warn 7, 8 and 9 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 15), // (26,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // System.Func x5 = (string? x) => // warn 12, 13 and 14 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(26, 27), // (26,36): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // System.Func x5 = (string? x) => // warn 12, 13 and 14 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(26, 36), // (26,51): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // System.Func x5 = (string? x) => // warn 12, 13 and 14 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(26, 51), // (28,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? x6 = null; // warn 15 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(28, 19), // (37,35): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void M4() { Event(new C()); } // warn 21 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(37, 35) }; var c = CreateCompilation(source); c.VerifyDiagnostics(expectedDiagnostics); var c2 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c2.VerifyDiagnostics( // (18,25): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'class' constraint. // string? local(C? x) // warn 7, 8 and 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("C", "T", "string?").WithLocation(18, 25), // (34,33): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'class' constraint. // static string M3(C x, C y) => throw null!; // warn 17 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "x").WithArguments("C", "T", "string?").WithLocation(34, 33), // (35,35): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'class' constraint. // delegate string? MyDelegate(C x); // warn 18 and 19 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("C", "T", "string?").WithLocation(35, 35), // (37,17): warning CS8602: Dereference of a possibly null reference. // void M4() { Event(new C()); } // warn 21 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "Event").WithLocation(37, 17), // (37,29): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'class' constraint. // void M4() { Event(new C()); } // warn 21 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("C", "T", "string?").WithLocation(37, 29), // (39,11): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'class' constraint. // class D2 : C { } // warn 23 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "D2").WithArguments("C", "T", "string?").WithLocation(39, 11), // (40,34): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'T?' doesn't match 'class' constraint. // public static C operator +(C x, C y) => throw null!; // warn 24 and 25 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "+").WithArguments("C", "T", "T?").WithLocation(40, 34), // (40,50): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'T?' doesn't match 'class' constraint. // public static C operator +(C x, C y) => throw null!; // warn 24 and 25 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "y").WithArguments("C", "T", "T?").WithLocation(40, 50), // (43,18): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'T?' doesn't match 'class' constraint. // D3(C x) => throw null!; // warn 26 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "x").WithArguments("C", "T", "T?").WithLocation(43, 18), // (45,36): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'class' constraint. // public string? this[C x] { get => throw null!; } // warn 27 and 28 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "x").WithArguments("C", "T", "string?").WithLocation(45, 36) ); var c3 = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); c3.VerifyDiagnostics(expectedDiagnostics); } [Fact] public void AnnotationWithoutNonNullTypes_GenericType() { var source = @" public class C where T : class { public T? M(T? x1) // warn 1 and 2 { T? y1 = x1; // warn 3 return y1; } } public class E where T : struct { public T? M(T? x2) { T? y2 = x2; return y2; } } "; CSharpCompilation c = CreateCompilation(source); c.VerifyDiagnostics( // (4,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public T? M(T? x1) // warn 1 and 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 18), // (4,17): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public T? M(T? x1) // warn 1 and 2 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 17), // (4,13): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public T? M(T? x1) // warn 1 and 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 13), // (4,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public T? M(T? x1) // warn 1 and 2 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 12), // (6,10): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? y1 = x1; // warn 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 10), // (6,9): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? y1 = x1; // warn 3 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(6, 9) ); var client = @" class Client { void M(C c) { c.M("""").ToString(); } } "; var comp2 = CreateCompilation(new[] { client }, options: WithNonNullTypesTrue(), references: new[] { c.ToMetadataReference() }); comp2.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // c.M("").ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, @"c.M("""")").WithLocation(6, 9) ); c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); comp2 = CreateCompilation(new[] { client }, options: WithNonNullTypesTrue(), references: new[] { c.EmitToImageReference() }); comp2.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // c.M("").ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, @"c.M("""")").WithLocation(6, 9) ); comp2 = CreateCompilation(new[] { client }, options: WithNonNullTypesTrue(), references: new[] { c.ToMetadataReference() }); comp2.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // c.M("").ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, @"c.M("""")").WithLocation(6, 9) ); } [Fact] public void AnnotationWithoutNonNullTypes_AttributeArgument() { var source = @"class AAttribute : System.Attribute { internal AAttribute(object o) { } } class B { } [A(typeof(object?))] // 1 class C1 { } [A(typeof(int?))] class C2 { } [A(typeof(B))] // 2 class C3 { } [A(typeof(B))] class C4 { }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,4): error CS8639: The typeof operator cannot be used on a nullable reference type // [A(typeof(object?))] // 1 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(object?)").WithLocation(6, 4), // (6,17): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // [A(typeof(object?))] // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 17), // (10,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // [A(typeof(B))] // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 19)); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,4): error CS8639: The typeof operator cannot be used on a nullable reference type // [A(typeof(object?))] // 1 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(object?)").WithLocation(6, 4)); } [Fact] public void Nullable_False_InCSharp7() { var comp = CreateCompilation("", options: WithNonNullTypesFalse(), parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); } [Fact] public void NullableOption() { var comp = CreateCompilation("", options: WithNonNullTypes(NullableContextOptions.Enable), parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics( // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.3", "preview").WithLocation(1, 1) ); comp = CreateCompilation("", options: WithNonNullTypes(NullableContextOptions.Warnings), parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics( // error CS8630: Invalid 'NullableContextOptions' value: 'Warnings' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Warnings", "7.3", "preview").WithLocation(1, 1) ); comp = CreateCompilation("", options: WithNonNullTypes(NullableContextOptions.Disable), parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(); comp = CreateCompilation("", options: WithNonNullTypes(NullableContextOptions.Enable), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); comp = CreateCompilation("", options: WithNonNullTypes(NullableContextOptions.Warnings), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); comp = CreateCompilation("", options: WithNonNullTypes(NullableContextOptions.Disable), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); comp = CreateCompilation(new string[] { }, options: WithNonNullTypes(NullableContextOptions.Enable), parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(); comp = CreateCompilation(new string[] { }, options: WithNonNullTypes(NullableContextOptions.Enable), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); comp = CreateCompilation(new string[] { }, options: WithNonNullTypes(NullableContextOptions.Warnings), parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(); comp = CreateCompilation(new string[] { }, options: WithNonNullTypes(NullableContextOptions.Warnings), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); comp = CreateCompilation(new string[] { }, options: WithNonNullTypes(NullableContextOptions.Disable), parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(); comp = CreateCompilation(new string[] { }, options: WithNonNullTypes(NullableContextOptions.Disable), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void NullableAttribute_NotRequiredCSharp7_01() { var source = @"using System.Threading.Tasks; class C { static async Task F() { return await Task.FromResult(default(string)); } }"; var comp = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.Regular7); comp.VerifyEmitDiagnostics(); } [Fact] public void NullableAttribute_NotRequiredCSharp7_02() { var source = @"using System; using System.Threading.Tasks; class C { static async Task F(Func f) { await G(async () => { await f(); return default(object); }); } static async Task G(Func> f) { throw new NotImplementedException(); } }"; var comp = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.Regular7); comp.VerifyEmitDiagnostics( // (13,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. // static async Task G(Func> f) Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "G").WithLocation(13, 32)); } [Fact, WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26618")] public void SuppressionOnNullConvertedToConstrainedTypeParameterType() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public T M() where T : C { return null!; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void MissingInt() { var source0 = @"namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Enum { } public class Attribute { } }"; var comp0 = CreateEmptyCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"enum E { A } class C { int F() => (int)E.A; }"; var comp = CreateEmptyCompilation( source, references: new[] { ref0 }, parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (1,6): error CS0518: Predefined type 'System.Int32' is not defined or imported // enum E { A } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "E").WithArguments("System.Int32").WithLocation(1, 6), // (4,5): error CS0518: Predefined type 'System.Int32' is not defined or imported // int F() => (int)E.A; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "int").WithArguments("System.Int32").WithLocation(4, 5), // (4,17): error CS0518: Predefined type 'System.Int32' is not defined or imported // int F() => (int)E.A; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "int").WithArguments("System.Int32").WithLocation(4, 17)); } [Fact] public void MissingNullable() { var source = @" namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Enum { } public class Attribute { } }"; var source2 = @" class C where T : struct { void M() { T? local = null; _ = local; } } "; var comp = CreateEmptyCompilation(new[] { source, source2 }); comp.VerifyDiagnostics( // (6,9): error CS0518: Predefined type 'System.Nullable`1' is not defined or imported // T? local = null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T?").WithArguments("System.Nullable`1").WithLocation(6, 9) ); var source3 = @" class C where T : struct { void M(T? nullable) { } } "; var comp2 = CreateEmptyCompilation(new[] { source, source3 }); comp2.VerifyDiagnostics( // (4,12): error CS0518: Predefined type 'System.Nullable`1' is not defined or imported // void M(T? nullable) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T?").WithArguments("System.Nullable`1").WithLocation(4, 12) ); var source4 = @" class C where T : struct { void M() where U : T? { } } "; var comp3 = CreateEmptyCompilation(new[] { source, source4 }); comp3.VerifyDiagnostics( // (4,27): error CS0518: Predefined type 'System.Nullable`1' is not defined or imported // void M() where U : T? { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T?").WithArguments("System.Nullable`1").WithLocation(4, 27), // (4,12): error CS0518: Predefined type 'System.Nullable`1' is not defined or imported // void M() where U : T? { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "U").WithArguments("System.Nullable`1").WithLocation(4, 12) ); } [ConditionalFact(typeof(DesktopOnly))] public void UnannotatedAssemblies_WithSomeExtraAnnotations() { // https://github.com/dotnet/roslyn/issues/29821 external annotations should be removed or fully designed/productized var comp = CreateCompilation(""); comp.VerifyDiagnostics(); var systemNamespace = comp.GetMember("System.Object").ContainingNamespace; var expected = ImmutableArray.Create( "System.String! System.String.Concat(System.String?, System.String?)", "System.Boolean System.Boolean.Parse(System.String!)", "void System.Buffer.BlockCopy(System.Array!, System.Int32, System.Array!, System.Int32, System.Int32)", "System.Byte System.Buffer.GetByte(System.Array!, System.Int32)", "void System.Buffer.SetByte(System.Array!, System.Int32, System.Byte)", "System.Int32 System.Buffer.ByteLength(System.Array!)", "System.Byte System.Byte.Parse(System.String!)", "System.Byte System.Byte.Parse(System.String!, System.Globalization.NumberStyles)", "System.Byte System.Byte.Parse(System.String!, System.IFormatProvider)", "System.Byte System.Byte.Parse(System.String!, System.Globalization.NumberStyles, System.IFormatProvider)" ); VerifyUsesOfNullability(systemNamespace, expected); } [Fact] public void AnnotatedAssemblies_WithSomeExtraAnnotations() { // https://github.com/dotnet/roslyn/issues/29821 external annotations should be removed or fully designed/productized var lib = @" namespace System { public class Object { } public struct Void { } public class Attribute { } public class ValueType { } public struct Boolean { } public class String { public String? Concat(String a, String b) => throw null!; } public class Enum { } public struct Byte { } public struct Int32 { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } } "; var comp = CreateEmptyCompilation(lib); comp.VerifyDiagnostics( // (11,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public String? Concat(String a, String b) => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 22) ); var comp2 = CreateEmptyCompilation("", references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics(); var expected = ImmutableArray.Create("System.String! System.String.Concat(System.String?, System.String?)"); var systemNamespace = comp2.GetMember("System.String").ContainingNamespace; VerifyUsesOfNullability(systemNamespace, expected); } [Fact] public void UnannotatedAssemblies_01() { var source0 = @"public class A { public static void F(string s) { } }"; var source1 = @"class B { static void Main() { A.F(string.Empty); A.F(null); } }"; TypeWithAnnotations getParameterType(Compilation c) => c.GetMember("A.F").Parameters[0].TypeWithAnnotations; // 7.0 library var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var compRefs0 = new MetadataReference[] { new CSharpCompilationReference(comp0) }; var metadataRefs0 = new[] { comp0.EmitToImageReference() }; Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp0).NullableAnnotation); // ... used in 7.0. var comp1 = CreateCompilation(source1, references: compRefs0, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(source1, references: metadataRefs0, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); // ... used in 8.0. comp1 = CreateCompilation(source1, references: compRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(source1, references: metadataRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); // 8.0 library comp0 = CreateCompilation(source0); comp0.VerifyDiagnostics(); compRefs0 = new MetadataReference[] { new CSharpCompilationReference(comp0) }; metadataRefs0 = new[] { comp0.EmitToImageReference() }; Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp0).NullableAnnotation); // ... used in 7.0. comp1 = CreateCompilation(source1, references: compRefs0, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(source1, references: metadataRefs0, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); // ... used in 8.0. comp1 = CreateCompilation(source1, references: compRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(source1, references: metadataRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: compRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: metadataRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, getParameterType(comp1).NullableAnnotation); // 8.0 library comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics(); compRefs0 = new MetadataReference[] { new CSharpCompilationReference(comp0) }; metadataRefs0 = new[] { comp0.EmitToImageReference() }; Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp0).NullableAnnotation); // ... used in 7.0. comp1 = CreateCompilation(source1, references: compRefs0, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(source1, references: metadataRefs0, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp1).NullableAnnotation); // ... used in 8.0. comp1 = CreateCompilation(source1, references: compRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(source1, references: metadataRefs0); comp1.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: compRefs0); comp1.VerifyDiagnostics( // (6,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // A.F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 13)); Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp1).NullableAnnotation); comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: metadataRefs0); comp1.VerifyDiagnostics( // (6,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // A.F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 13)); Assert.Equal(NullableAnnotation.NotAnnotated, getParameterType(comp1).NullableAnnotation); } [Fact] public void UnannotatedAssemblies_02() { var source0 = @"#pragma warning disable 67 public delegate void D(); public class C { public object F; public event D E; public object P => null; public object this[object o] => null; public object M(object o) => null; }"; var source1 = @"class P { static void F(C c) { object o; o = c.F; c.E += null; o = c.P; o = c[null]; o = c.M(null); } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); void verify(Compilation c) { c.VerifyDiagnostics(); Assert.Equal(NullableAnnotation.Oblivious, c.GetMember("C.F").TypeWithAnnotations.NullableAnnotation); Assert.Equal(NullableAnnotation.Oblivious, c.GetMember("C.E").TypeWithAnnotations.NullableAnnotation); Assert.Equal(NullableAnnotation.Oblivious, c.GetMember("C.P").TypeWithAnnotations.NullableAnnotation); var indexer = c.GetMember("C.this[]"); Assert.Equal(NullableAnnotation.Oblivious, indexer.TypeWithAnnotations.NullableAnnotation); Assert.Equal(NullableAnnotation.Oblivious, indexer.Parameters[0].TypeWithAnnotations.NullableAnnotation); var method = c.GetMember("C.M"); Assert.Equal(NullableAnnotation.Oblivious, method.ReturnTypeWithAnnotations.NullableAnnotation); Assert.Equal(NullableAnnotation.Oblivious, method.Parameters[0].TypeWithAnnotations.NullableAnnotation); } var comp1A = CreateCompilation(source1, references: new MetadataReference[] { new CSharpCompilationReference(comp0) }); verify(comp1A); var comp1B = CreateCompilation(source1, references: new[] { comp0.EmitToImageReference() }); verify(comp1B); } [Fact] public void UnannotatedAssemblies_03() { var source0 = @"#pragma warning disable 67 public class C { public (object, object) F; public (object, object) P => (null, null); public (object, object) M((object, object) o) => o; }"; var source1 = @"class P { static void F(C c) { (object, object) t; t = c.F; t = c.P; t = c.M((null, null)); } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); void verifyTuple(TypeWithAnnotations type) { var tuple = (TupleTypeSymbol)type.Type; Assert.Equal(NullableAnnotation.Oblivious, tuple.TupleElements[0].TypeWithAnnotations.NullableAnnotation); Assert.Equal(NullableAnnotation.Oblivious, tuple.TupleElements[1].TypeWithAnnotations.NullableAnnotation); } void verify(Compilation c) { c.VerifyDiagnostics(); verifyTuple(c.GetMember("C.F").TypeWithAnnotations); verifyTuple(c.GetMember("C.P").TypeWithAnnotations); var method = c.GetMember("C.M"); verifyTuple(method.ReturnTypeWithAnnotations); verifyTuple(method.Parameters[0].TypeWithAnnotations); } var comp1A = CreateCompilation(source1, references: new[] { new CSharpCompilationReference(comp0) }); verify(comp1A); var comp1B = CreateCompilation(source1, references: new[] { comp0.EmitToImageReference() }); verify(comp1B); } [Fact] public void UnannotatedAssemblies_04() { var source = @"class A { } class B : A { } interface I where T : A { } abstract class C where T : A { internal abstract void M() where U : T; } class D : C, I { internal override void M() { } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); var derivedType = comp.GetMember("D"); var baseType = derivedType.BaseTypeNoUseSiteDiagnostics; var constraintType = baseType.TypeParameters.Single().ConstraintTypesNoUseSiteDiagnostics.Single(); Assert.Equal(NullableAnnotation.Oblivious, constraintType.NullableAnnotation); var interfaceType = derivedType.Interfaces().Single(); constraintType = interfaceType.TypeParameters.Single().ConstraintTypesNoUseSiteDiagnostics.Single(); Assert.Equal(NullableAnnotation.Oblivious, constraintType.NullableAnnotation); var method = baseType.GetMember("M"); constraintType = method.TypeParameters.Single().ConstraintTypesNoUseSiteDiagnostics.Single(); Assert.Equal(NullableAnnotation.Oblivious, constraintType.NullableAnnotation); } [Fact] public void UnannotatedAssemblies_05() { var source = @"interface I { I F(I t); } class C : I { I I.F(I s) => null; }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); var type = comp.GetMember("C"); var interfaceType = type.Interfaces().Single(); var typeArg = interfaceType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single(); Assert.Equal(NullableAnnotation.Oblivious, typeArg.NullableAnnotation); var method = type.GetMember("I.F"); Assert.Equal(NullableAnnotation.Oblivious, method.ReturnTypeWithAnnotations.NullableAnnotation); typeArg = ((NamedTypeSymbol)method.ReturnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single(); Assert.Equal(NullableAnnotation.Oblivious, typeArg.NullableAnnotation); var parameter = method.Parameters.Single(); Assert.Equal(NullableAnnotation.Oblivious, parameter.TypeWithAnnotations.NullableAnnotation); typeArg = ((NamedTypeSymbol)parameter.Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single(); Assert.Equal(NullableAnnotation.Oblivious, typeArg.NullableAnnotation); } [Fact] public void UnannotatedAssemblies_06() { var source0 = @"public class C { public T F; } public class C { public static C Create(T t) => new C(); }"; var source1 = @"class P { static void F(object x, object? y) { object z; z = C.Create(x).F; z = C.Create(y).F; } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { comp0.EmitToImageReference() }); comp1.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // z = C.Create(y).F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "C.Create(y).F").WithLocation(7, 13)); } [Fact] public void UnannotatedAssemblies_07() { var source0 = @"public interface I { object F(object o); }"; var source1 = @"class A1 : I { object I.F(object? o) => new object(); } class A2 : I { object? I.F(object o) => o; } class B1 : I { public object F(object? o) => new object(); } class B2 : I { public object? F(object o) => o; } class C1 { public object F(object? o) => new object(); } class C2 { public object? F(object o) => o; } class D1 : C1, I { } class D2 : C2, I { } class P { static void F(object? x, A1 a1, A2 a2) { object y; y = ((I)a1).F(x); y = ((I)a2).F(x); } static void F(object? x, B1 b1, B2 b2) { object y; y = b1.F(x); y = b2.F(x); y = ((I)b1).F(x); y = ((I)b2).F(x); } static void F(object? x, D1 d1, D2 d2) { object y; y = d1.F(x); y = d2.F(x); y = ((I)d1).F(x); y = ((I)d2).F(x); } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new MetadataReference[] { new CSharpCompilationReference(comp0) }); comp1.VerifyDiagnostics( // (43,18): warning CS8604: Possible null reference argument for parameter 'o' in 'object? B2.F(object o)'. // y = b2.F(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("o", "object? B2.F(object o)").WithLocation(43, 18), // (43,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = b2.F(x); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b2.F(x)").WithLocation(43, 13), // (51,18): warning CS8604: Possible null reference argument for parameter 'o' in 'object? C2.F(object o)'. // y = d2.F(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("o", "object? C2.F(object o)").WithLocation(51, 18), // (51,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = d2.F(x); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "d2.F(x)").WithLocation(51, 13)); comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { comp0.EmitToImageReference() }); comp1.VerifyDiagnostics( // (43,18): warning CS8604: Possible null reference argument for parameter 'o' in 'object? B2.F(object o)'. // y = b2.F(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("o", "object? B2.F(object o)").WithLocation(43, 18), // (43,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = b2.F(x); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b2.F(x)").WithLocation(43, 13), // (51,18): warning CS8604: Possible null reference argument for parameter 'o' in 'object? C2.F(object o)'. // y = d2.F(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("o", "object? C2.F(object o)").WithLocation(51, 18), // (51,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = d2.F(x); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "d2.F(x)").WithLocation(51, 13)); } [Fact] public void UnannotatedAssemblies_08() { var source0 = @"public interface I { object? F(object? o); object G(object o); }"; var source1 = @"public class A : I { object I.F(object o) => null; object I.G(object o) => null; } public class B : I { public object F(object o) => null; public object G(object o) => null; } public class C { public object F(object o) => null; public object G(object o) => null; } public class D : C { }"; var source2 = @"class P { static void F(object o, A a) { ((I)a).F(o).ToString(); ((I)a).G(null).ToString(); } static void F(object o, B b) { b.F(o).ToString(); b.G(null).ToString(); ((I)b).F(o).ToString(); ((I)b).G(null).ToString(); } static void F(object o, D d) { d.F(o).ToString(); d.G(null).ToString(); ((I)d).F(o).ToString(); ((I)d).G(null).ToString(); } }"; var comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var comp1 = CreateCompilation(source1, references: new[] { ref0 }, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); var ref1 = comp1.EmitToImageReference(); var comp2A = CreateCompilation(source2, references: new[] { ref0, ref1 }, parseOptions: TestOptions.Regular7); comp2A.VerifyDiagnostics(); var comp2B = CreateCompilation(source2, references: new[] { ref0, ref1 }); comp2B.VerifyDiagnostics(); var comp2C = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { ref0, ref1 }); comp2C.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // ((I)a).F(o).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((I)a).F(o)").WithLocation(5, 9), // (6,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((I)a).G(null).ToString(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 18), // (12,9): warning CS8602: Dereference of a possibly null reference. // ((I)b).F(o).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((I)b).F(o)").WithLocation(12, 9), // (13,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((I)b).G(null).ToString(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 18), // (19,9): warning CS8602: Dereference of a possibly null reference. // ((I)d).F(o).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((I)d).F(o)").WithLocation(19, 9), // (20,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((I)d).G(null).ToString(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(20, 18)); var comp2D = CreateCompilation(new[] { source2 }, options: WithNonNullTypesFalse(), references: new[] { ref0, ref1 }); comp2D.VerifyDiagnostics(); } [Fact] public void UnannotatedAssemblies_09() { var source0 = @"public abstract class A { public abstract object? F(object x, object? y); }"; var source1 = @"public abstract class B : A { public abstract override object F(object x, object y); public abstract object G(object x, object y); }"; var source2 = @"class C1 : B { public override object F(object x, object y) => x; public override object G(object x, object y) => x; } class C2 : B { public override object? F(object? x, object? y) => x; public override object? G(object? x, object? y) => x; } class P { static void F(object? x, object y, C1 c) { c.F(x, y).ToString(); c.G(x, y).ToString(); ((B)c).F(x, y).ToString(); ((B)c).G(x, y).ToString(); ((A)c).F(x, y).ToString(); } static void F(object? x, object y, C2 c) { c.F(x, y).ToString(); c.G(x, y).ToString(); ((B)c).F(x, y).ToString(); ((B)c).G(x, y).ToString(); ((A)c).F(x, y).ToString(); } }"; var comp0 = CreateCompilation(source0); comp0.VerifyDiagnostics( // (3,47): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract object? F(object x, object? y); Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 47), // (3,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract object? F(object x, object? y); Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 27) ); var ref0 = comp0.EmitToImageReference(); var comp1 = CreateCompilation(source1, references: new[] { ref0 }, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); var ref1 = comp1.EmitToImageReference(); var comp2 = CreateCompilation(source2, references: new[] { ref0, ref1 }); comp2.VerifyDiagnostics( // (9,37): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override object? G(object? x, object? y) => x; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 37), // (9,48): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override object? G(object? x, object? y) => x; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 48), // (9,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override object? G(object? x, object? y) => x; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 27), // (21,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void F(object? x, object y, C2 c) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 25), // (13,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void F(object? x, object y, C1 c) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 25), // (8,37): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override object? F(object? x, object? y) => x; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 37), // (8,48): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override object? F(object? x, object? y) => x; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 48), // (8,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override object? F(object? x, object? y) => x; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 27) ); comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics(); ref0 = comp0.EmitToImageReference(); comp1 = CreateCompilation(source1, references: new[] { ref0 }, parseOptions: TestOptions.Regular7); comp1.VerifyDiagnostics(); ref1 = comp1.EmitToImageReference(); comp2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { ref0, ref1 }); comp2.VerifyDiagnostics( // (15,13): warning CS8604: Possible null reference argument for parameter 'x' in 'object C1.F(object x, object y)'. // c.F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "object C1.F(object x, object y)").WithLocation(15, 13), // (16,13): warning CS8604: Possible null reference argument for parameter 'x' in 'object C1.G(object x, object y)'. // c.G(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "object C1.G(object x, object y)").WithLocation(16, 13), // (19,18): warning CS8604: Possible null reference argument for parameter 'x' in 'object? A.F(object x, object? y)'. // ((A)c).F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "object? A.F(object x, object? y)").WithLocation(19, 18), // (19,9): warning CS8602: Dereference of a possibly null reference. // ((A)c).F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A)c).F(x, y)").WithLocation(19, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // c.F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F(x, y)").WithLocation(23, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // c.G(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.G(x, y)").WithLocation(24, 9), // (27,18): warning CS8604: Possible null reference argument for parameter 'x' in 'object? A.F(object x, object? y)'. // ((A)c).F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "object? A.F(object x, object? y)").WithLocation(27, 18), // (27,9): warning CS8602: Dereference of a possibly null reference. // ((A)c).F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A)c).F(x, y)").WithLocation(27, 9)); } [Fact] public void UnannotatedAssemblies_10() { var source0 = @"public abstract class A { public T F; } public sealed class B : A { }"; var source1 = @"class C { static void Main() { B b = new B(); b.F = null; } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var comp1 = CreateCompilation(source1, references: new MetadataReference[] { new CSharpCompilationReference(comp0) }); comp1.VerifyDiagnostics(); comp1 = CreateCompilation(source1, references: new[] { comp0.EmitToImageReference() }); comp1.VerifyDiagnostics(); } [Fact] public void Embedded_WithObsolete() { string source = @" namespace Microsoft.CodeAnalysis { [Embedded] [System.Obsolete(""obsolete"")] class EmbeddedAttribute : System.Attribute { public EmbeddedAttribute() { } } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); Assert.False(comp.GetMember("Microsoft.CodeAnalysis.EmbeddedAttribute").IsImplicitlyDeclared); } [Fact] public void NonNullTypes_Cycle5() { string source = @" namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] class SomeAttribute : Attribute { public SomeAttribute() { } public int Property { get; set; } } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NonNullTypes_Cycle12() { string source = @" [System.Flags] enum E { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NonNullTypes_Cycle13() { string source = @" interface I { } [System.Obsolete(nameof(I2))] interface I2 : I { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NonNullTypes_Cycle15() { string lib_cs = "public class Base { }"; var lib = CreateCompilation(lib_cs, assemblyName: "lib"); string lib2_cs = "public class C : Base { }"; var lib2 = CreateCompilation(lib2_cs, references: new[] { lib.EmitToImageReference() }, assemblyName: "lib2"); string source_cs = @" [D] class DAttribute : C { } "; var comp = CreateCompilation(source_cs, references: new[] { lib2.EmitToImageReference() }); comp.VerifyDiagnostics( // (3,20): error CS0012: The type 'Base' is defined in an assembly that is not referenced. You must add a reference to assembly 'lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // class DAttribute : C { } Diagnostic(ErrorCode.ERR_NoTypeDef, "C").WithArguments("Base", "lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(3, 20), // (2,2): error CS0012: The type 'Base' is defined in an assembly that is not referenced. You must add a reference to assembly 'lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // [D] Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("Base", "lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(2, 2), // (2,2): error CS0012: The type 'Base' is defined in an assembly that is not referenced. You must add a reference to assembly 'lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // [D] Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("Base", "lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(2, 2) ); } [Fact] public void NonNullTypes_Cycle16() { string source = @" using System; [AttributeUsage(AttributeTargets.Property)] class AttributeWithProperty : System.ComponentModel.DisplayNameAttribute { public override string DisplayName { get => throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NonNullTypes_OnFields() { var obliviousLib = @" public class Oblivious { public static string s; } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); var lib = @" #nullable enable public class External { public static string s; public static string? ns; #nullable disable public static string fs; #nullable disable public static string? fns; } "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); libComp.VerifyDiagnostics( // (13,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static string? fns; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 25) ); var source = @" #nullable disable public class OuterA { #nullable enable public class A { public static string s; public static string? ns; } } // NonNullTypes(true) by default public class B { public static string s; public static string? ns; } #nullable disable public class C { #nullable enable public static string s; #nullable enable public static string? ns; } #nullable disable public class OuterD { public class D { #nullable enable public static string s; #nullable enable public static string? ns; } } public class Oblivious2 { #nullable disable public static string s; #nullable disable public static string? ns; } #nullable enable class E { public void M() { Oblivious.s /*T:string!*/ = null; External.s /*T:string!*/ = null; // warn 1 External.ns /*T:string?*/ = null; External.fs /*T:string!*/ = null; External.fns /*T:string?*/ = null; OuterA.A.s /*T:string!*/ = null; // warn 2 OuterA.A.ns /*T:string?*/ = null; B.s /*T:string!*/ = null; // warn 3 B.ns /*T:string?*/ = null; C.s /*T:string!*/ = null; // warn 4 C.ns /*T:string?*/ = null; OuterD.D.s /*T:string!*/ = null; // warn 5 OuterD.D.ns /*T:string?*/ = null; Oblivious2.s /*T:string!*/ = null; Oblivious2.ns /*T:string?*/ = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference(), libComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (49,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static string? ns; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(49, 25), // (58,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // External.s /*T:string!*/ = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(58, 36), // (64,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterA.A.s /*T:string!*/ = null; // warn 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(64, 36), // (67,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // B.s /*T:string!*/ = null; // warn 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(67, 29), // (70,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // C.s /*T:string!*/ = null; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(70, 29), // (73,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterD.D.s /*T:string!*/ = null; // warn 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(73, 36) ); } [Fact] public void SuppressedNullConvertedToUnconstrainedT() { var source = @" public class List2 { public T Item { get; set; } = null!; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,55): error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead. // public class List2 { public T Item { get; set; } = null!; } Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(2, 55) ); } [Fact] public void TwiceSuppressedNullConvertedToUnconstrainedT() { var source = @" public class List2 { public T Item { get; set; } = null!!; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,55): error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead. // public class List2 { public T Item { get; set; } = null!!; } Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(2, 55) ); } [Fact] public void NonNullTypes_OnFields_Nested() { var obliviousLib = @" public class List1 { public T Item { get; set; } = default(T); } public class Oblivious { public static List1 s; } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); var lib = @" using System.Diagnostics.CodeAnalysis; public class List2 { public T Item { get; set; } = default!; } public class External { public static List2 s; public static List2 ns; #nullable disable public static List2 fs; #nullable disable public static List2 fns; } "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); var source = @" public class List3 { public T Item { get; set; } = default!; } #nullable disable public class OuterA { #nullable enable public class A { public static List3 s; public static List3 ns; } } // NonNullTypes(true) by default public class B { public static List3 s; public static List3 ns; } #nullable disable public class OuterD { public class D { #nullable enable public static List3 s; #nullable enable public static List3 ns; } } #nullable disable public class Oblivious2 { public static List3 s; public static List3 ns; } #nullable enable class E { public void M() { Oblivious.s.Item /*T:string!*/ = null; External.s.Item /*T:string!*/ = null; // warn 1 External.ns.Item /*T:string?*/ = null; External.fs.Item /*T:string!*/ = null; External.fns.Item /*T:string?*/ = null; OuterA.A.s.Item /*T:string!*/ = null; // warn 2 OuterA.A.ns.Item /*T:string?*/ = null; B.s.Item /*T:string!*/ = null; // warn 3 B.ns.Item /*T:string?*/ = null; OuterD.D.s.Item /*T:string!*/ = null; // warn 4 OuterD.D.ns.Item /*T:string?*/ = null; Oblivious2.s.Item /*T:string!*/ = null; Oblivious2.ns.Item /*T:string?*/ = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference(), libComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (39,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static List3 ns; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(39, 31), // (48,41): warning CS8625: Cannot convert null literal to non-nullable reference type. // External.s.Item /*T:string!*/ = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 41), // (54,41): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterA.A.s.Item /*T:string!*/ = null; // warn 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(54, 41), // (57,34): warning CS8625: Cannot convert null literal to non-nullable reference type. // B.s.Item /*T:string!*/ = null; // warn 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(57, 34), // (60,41): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterD.D.s.Item /*T:string!*/ = null; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(60, 41)); } [Fact] public void NonNullTypes_OnFields_Tuples() { var obliviousLib = @" public class Oblivious { public static (string s, string s2) t; } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); var lib = @" public class External { public static (string s, string? ns) t; } "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); var source = @" #nullable disable public class OuterA { #nullable enable public class A { public static (string s, string? ns) t; } } // NonNullTypes(true) by default public class B { public static (string s, string? ns) t; } #nullable disable public class OuterD { public class D { #nullable enable public static (string s, string? ns) t; } } #nullable disable public class Oblivious2 { public static (string s, string? ns) t; } #nullable enable class E { public void M() { Oblivious.t.s /*T:string!*/ = null; External.t.s /*T:string!*/ = null; // warn 1 External.t.ns /*T:string?*/ = null; OuterA.A.t.s /*T:string!*/ = null; // warn 2 OuterA.A.t.ns /*T:string?*/ = null; B.t.s /*T:string!*/ = null; // warn 3 B.t.ns /*T:string?*/ = null; OuterD.D.t.s /*T:string!*/ = null; // warn 4 OuterD.D.t.ns /*T:string?*/ = null; Oblivious2.t.s /*T:string!*/ = null; Oblivious2.t.ns /*T:string?*/ = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference(), libComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (33,36): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static (string s, string? ns) t; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(33, 36), // (42,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // External.t.s /*T:string!*/ = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(42, 38), // (45,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterA.A.t.s /*T:string!*/ = null; // warn 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(45, 38), // (48,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // B.t.s /*T:string!*/ = null; // warn 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 31), // (51,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterD.D.t.s /*T:string!*/ = null; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(51, 38) ); } [Fact] public void NonNullTypes_OnFields_Arrays() { var obliviousLib = @" public class Oblivious { public static string[] s; } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); var lib = @" public class External { public static string[] s; public static string?[] ns; } "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); var source = @" #nullable disable public class OuterA { #nullable enable public class A { public static string[] s; public static string?[] ns; } } // NonNullTypes(true) by default public class B { public static string[] s; public static string?[] ns; } #nullable disable public class OuterD { public class D { #nullable enable public static string[] s; #nullable enable public static string?[] ns; } } #nullable disable public class Oblivious2 { public static string[] s; public static string?[] ns; } #nullable enable class E { public void M() { Oblivious.s[0] /*T:string!*/ = null; External.s[0] /*T:string!*/ = null; // warn 1 External.ns[0] /*T:string?*/ = null; OuterA.A.s[0] /*T:string!*/ = null; // warn 2 OuterA.A.ns[0] /*T:string?*/ = null; B.s[0] /*T:string!*/ = null; // warn 3 B.ns[0] /*T:string?*/ = null; OuterD.D.s[0] /*T:string!*/ = null; // warn 4 OuterD.D.ns[0] /*T:string?*/ = null; Oblivious2.s[0] /*T:string!*/ = null; Oblivious2.ns[0] /*T:string?*/ = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference(), libComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (38,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static string?[] ns; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(38, 25), // (47,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // External.s[0] /*T:string!*/ = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(47, 39), // (50,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterA.A.s[0] /*T:string!*/ = null; // warn 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(50, 39), // (53,32): warning CS8625: Cannot convert null literal to non-nullable reference type. // B.s[0] /*T:string!*/ = null; // warn 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(53, 32), // (56,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterD.D.s[0] /*T:string!*/ = null; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(56, 39) ); } [Fact] public void NonNullTypes_OnProperties() { var obliviousLib = @" public class Oblivious { public static string s { get; set; } } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); obliviousComp.VerifyDiagnostics(); var lib = @" public class External { public static string s { get; set; } public static string? ns { get; set; } } "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); var source = @" #nullable disable public class OuterA { public class A { #nullable enable public static string s { get; set; } #nullable enable public static string? ns { get; set; } } } // NonNullTypes(true) by default public class B { public static string s { get; set; } public static string? ns { get; set; } } #nullable disable public class OuterD { #nullable enable public class D { public static string s { get; set; } public static string? ns { get; set; } } } public class Oblivious2 { #nullable disable public static string s { get; set; } #nullable disable public static string? ns { get; set; } } #nullable enable class E { public void M() { Oblivious.s /*T:string!*/ = null; External.s /*T:string!*/ = null; // warn 1 External.ns /*T:string?*/ = null; OuterA.A.s /*T:string!*/ = null; // warn 2 OuterA.A.ns /*T:string?*/ = null; B.s /*T:string!*/ = null; // warn 3 B.ns /*T:string?*/ = null; OuterD.D.s /*T:string!*/ = null; // warn 4 OuterD.D.ns /*T:string?*/ = null; Oblivious2.s /*T:string!*/ = null; Oblivious2.ns /*T:string?*/ = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference(), libComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (39,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static string? ns { get; set; } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(39, 25), // (48,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // External.s /*T:string!*/ = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 36), // (51,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterA.A.s /*T:string!*/ = null; // warn 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(51, 36), // (54,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // B.s /*T:string!*/ = null; // warn 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(54, 29), // (57,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterD.D.s /*T:string!*/ = null; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(57, 36) ); } [Fact] public void NonNullTypes_OnMethods() { var obliviousLib = @" public class Oblivious { public static string Method(string s) => throw null; } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); var lib = @" public class External { public static string Method(string s) => throw null!; public static string? NMethod(string? ns) => throw null!; } "; var libComp = CreateCompilation(new[] { lib }, options: WithNonNullTypesTrue()); var source = @" #nullable disable public class OuterA { #nullable enable public class A { public static string Method(string s) => throw null!; public static string? NMethod(string? ns) => throw null!; } } // NonNullTypes(true) by default public class B { public static string Method(string s) => throw null!; public static string? NMethod(string? ns) => throw null!; } #nullable disable public class OuterD { public class D { #nullable enable public static string Method(string s) => throw null!; #nullable enable public static string? NMethod(string? ns) => throw null!; } } #nullable disable public class Oblivious2 { public static string Method(string s) => throw null!; public static string? NMethod(string? ns) => throw null!; } #nullable enable class E { public void M() { Oblivious.Method(null) /*T:string!*/; External.Method(null) /*T:string!*/; // warn 1 External.NMethod(null) /*T:string?*/; OuterA.A.Method(null) /*T:string!*/; // warn 2 OuterA.A.NMethod(null) /*T:string?*/; B.Method(null) /*T:string!*/; // warn 3 B.NMethod(null) /*T:string?*/; OuterD.D.Method(null) /*T:string!*/; // warn 4 OuterD.D.NMethod(null) /*T:string?*/; Oblivious2.Method(null) /*T:string!*/; Oblivious2.NMethod(null) /*T:string?*/; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference(), libComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (38,41): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static string? NMethod(string? ns) => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(38, 41), // (38,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static string? NMethod(string? ns) => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(38, 25), // (47,25): warning CS8625: Cannot convert null literal to non-nullable reference type. // External.Method(null) /*T:string!*/; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(47, 25), // (50,25): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterA.A.Method(null) /*T:string!*/; // warn 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(50, 25), // (53,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // B.Method(null) /*T:string!*/; // warn 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(53, 18), // (56,25): warning CS8625: Cannot convert null literal to non-nullable reference type. // OuterD.D.Method(null) /*T:string!*/; // warn 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(56, 25) ); } [Fact] public void NonNullTypes_OnModule() { var obliviousLib = @"#nullable disable public class Oblivious { } "; var obliviousComp = CreateCompilation(new[] { obliviousLib }); obliviousComp.VerifyDiagnostics(); var compilation = CreateCompilation("", options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference() }); compilation.VerifyDiagnostics(); } [Fact] public void NonNullTypes_ValueTypeArgument() { var source = @"#nullable disable class A { } class B { A P { get; } }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); } [WorkItem(28324, "https://github.com/dotnet/roslyn/issues/28324")] [Fact] public void NonNullTypes_GenericOverriddenMethod_ValueType() { var source = @"#nullable disable class C { } abstract class A { internal abstract C F() where T : struct; } class B : A { internal override C F() => throw null!; }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); var method = comp.GetMember("A.F"); var typeArg = ((NamedTypeSymbol)method.ReturnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0]; Assert.True(typeArg.Type.IsValueType); Assert.Equal(NullableAnnotation.Oblivious, typeArg.NullableAnnotation); method = comp.GetMember("B.F"); typeArg = ((NamedTypeSymbol)method.ReturnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0]; Assert.True(typeArg.Type.IsValueType); Assert.Equal(NullableAnnotation.Oblivious, typeArg.NullableAnnotation); // https://github.com/dotnet/roslyn/issues/29843: Test all combinations of base and derived // including explicit Nullable. } // BoundExpression.Type for Task.FromResult(_f[0]) is Task // but the inferred type is Task. [Fact] public void CompareUnannotatedAndNonNullableTypeParameter() { var source = @"#pragma warning disable 0649 using System.Threading.Tasks; class C { T[] _f; Task F() => Task.FromResult(_f[0]); }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8618: Non-nullable field '_f' is uninitialized. // T[] _f; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "_f").WithArguments("field", "_f").WithLocation(5, 9) ); } [Fact] public void CircularConstraints() { var source = @"class A where T : B.I { internal interface I { } } class B : A where T : A.I { }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular7, skipUsesIsNullable: true); comp.VerifyDiagnostics( // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.0. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.0", "preview").WithLocation(1, 1) ); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(27686, "https://github.com/dotnet/roslyn/issues/27686")] public void AssignObliviousIntoLocals() { var obliviousLib = @" public class Oblivious { public static string f; } "; var obliviousComp = CreateCompilation(obliviousLib, parseOptions: TestOptions.Regular7); var source = @" class C { void M() { string s = Oblivious.f; s /*T:string!*/ .ToString(); string ns = Oblivious.f; ns /*T:string!*/ .ToString(); } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { obliviousComp.EmitToImageReference() }); compilation.VerifyTypes(); compilation.VerifyDiagnostics(); } [Fact] public void NonNullTypesTrue_Foreach() { var source = @" class C { #nullable enable public void M2() { foreach (string s in Collection()) { s /*T:string!*/ .ToString(); } foreach (string? ns in NCollection()) { ns /*T:string?*/ .ToString(); // 1 } foreach (var s1 in Collection()) { s1 /*T:string!*/ .ToString(); } foreach (var ns1 in NCollection()) { ns1 /*T:string?*/ .ToString(); // 2 } foreach (string s in FalseCollection()) { s /*T:string!*/ .ToString(); } foreach (string? ns in FalseNCollection()) { ns /*T:string?*/ .ToString(); // 3 } foreach (var s1 in FalseCollection()) { s1 /*T:string!*/ .ToString(); } foreach (var ns1 in FalseNCollection()) { ns1 /*T:string?*/ .ToString(); // 4 } } #nullable enable string[] Collection() => throw null!; #nullable enable string?[] NCollection() => throw null!; #nullable disable string[] FalseCollection() => throw null!; #nullable disable string?[] FalseNCollection() => throw null!; // 5 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (60,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string?[] FalseNCollection() => throw null!; // 5 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(60, 11), // (16,13): warning CS8602: Dereference of a possibly null reference. // ns /*T:string?*/ .ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns").WithLocation(16, 13), // (26,13): warning CS8602: Dereference of a possibly null reference. // ns1 /*T:string?*/ .ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns1").WithLocation(26, 13), // (36,13): warning CS8602: Dereference of a possibly null reference. // ns /*T:string?*/ .ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns").WithLocation(36, 13), // (46,13): warning CS8602: Dereference of a possibly null reference. // ns1 /*T:string?*/ .ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns1").WithLocation(46, 13) ); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void NonNullTypesFalse_Foreach() { var source = @" class C { #nullable disable public void M2() { foreach (string s in Collection()) { s /*T:string!*/ .ToString(); } foreach (string? ns in NCollection()) // 1 { ns /*T:string?*/ .ToString(); } foreach (var s1 in Collection()) { s1 /*T:string!*/ .ToString(); } foreach (var ns1 in NCollection()) { ns1 /*T:string?*/ .ToString(); } foreach (string s in FalseCollection()) { s /*T:string!*/ .ToString(); } foreach (string? ns in FalseNCollection()) // 2 { ns /*T:string?*/ .ToString(); } foreach (var s1 in FalseCollection()) { s1 /*T:string!*/ .ToString(); } foreach (var ns1 in FalseNCollection()) { ns1 /*T:string?*/ .ToString(); } } #nullable enable string[] Collection() => throw null!; #nullable enable string?[] NCollection() => throw null!; #nullable disable string[] FalseCollection() => throw null!; #nullable disable string?[] FalseNCollection() => throw null!; // 3 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (60,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string?[] FalseNCollection() => throw null!; // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(60, 11), // (14,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // foreach (string? ns in NCollection()) // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 24), // (34,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // foreach (string? ns in FalseNCollection()) // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(34, 24) ); } [Fact] public void NonNullTypesTrue_OutVars() { var source = @" class C { #nullable enable public void M() { Out(out string s2); s2 /*T:string!*/ .ToString(); s2 = null; // 1 NOut(out string? ns2); ns2 /*T:string?*/ .ToString(); // 2 ns2 = null; FalseOut(out string s3); s3 /*T:string!*/ .ToString(); s3 = null; // 3 FalseNOut(out string? ns3); ns3 /*T:string?*/ .ToString(); // 4 ns3 = null; Out(out var s4); s4 /*T:string!*/ .ToString(); s4 = null; // 5 NOut(out var ns4); ns4 /*T:string?*/ .ToString(); // 6 ns4 = null; FalseOut(out var s5); s5 /*T:string!*/ .ToString(); s5 = null; // 7 FalseNOut(out var ns5); ns5 /*T:string?*/ .ToString(); // 8 ns5 = null; } #nullable enable void Out(out string s) => throw null!; #nullable enable void NOut(out string? ns) => throw null!; #nullable disable void FalseOut(out string s) => throw null!; #nullable disable void FalseNOut(out string? ns) => throw null!; // 9 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (52,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void FalseNOut(out string? ns) => throw null!; // 9 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(52, 30), // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 14), // (14,9): warning CS8602: Dereference of a possibly null reference. // ns2 /*T:string?*/ .ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns2").WithLocation(14, 9), // (19,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s3 = null; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(19, 14), // (22,9): warning CS8602: Dereference of a possibly null reference. // ns3 /*T:string?*/ .ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns3").WithLocation(22, 9), // (27,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s4 = null; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(27, 14), // (30,9): warning CS8602: Dereference of a possibly null reference. // ns4 /*T:string?*/ .ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns4").WithLocation(30, 9), // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s5 = null; // 7 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(35, 14), // (38,9): warning CS8602: Dereference of a possibly null reference. // ns5 /*T:string?*/ .ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns5").WithLocation(38, 9) ); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void NonNullTypesFalse_OutVars() { var source = @" class C { #nullable disable public void M() { Out(out string s2); s2 /*T:string!*/ .ToString(); s2 = null; NOut(out string? ns2); // 1 ns2 /*T:string?*/ .ToString(); // 2 ns2 = null; FalseOut(out string s3); s3 /*T:string!*/ .ToString(); s3 = null; FalseNOut(out string? ns3); // 3 ns3 /*T:string?*/ .ToString(); // 4 ns3 = null; Out(out var s4); s4 /*T:string!*/ .ToString(); s4 = null; // 5 NOut(out var ns4); ns4 /*T:string?*/ .ToString(); // 6 ns4 = null; FalseOut(out var s5); s5 /*T:string!*/ .ToString(); s5 = null; FalseNOut(out var ns5); ns5 /*T:string?*/ .ToString(); // 7 ns5 = null; } #nullable enable void Out(out string s) => throw null!; #nullable enable void NOut(out string? ns) => throw null!; #nullable disable void FalseOut(out string s) => throw null!; #nullable disable void FalseNOut(out string? ns) => throw null!; // 8 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (52,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void FalseNOut(out string? ns) => throw null!; // 8 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(52, 30), // (13,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // NOut(out string? ns2); // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 24), // (21,29): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // FalseNOut(out string? ns3); // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 29) ); } [Fact] public void NonNullTypesTrue_LocalDeclarations() { var source = @" #nullable enable public class C : Base { public void M() { string s2 = Method(); s2 /*T:string!*/ .ToString(); s2 = null; // warn 1 string? ns2 = NMethod(); ns2 /*T:string?*/ .ToString(); // warn 2 ns2 = null; string s3 = FalseMethod(); s3 /*T:string!*/ .ToString(); s3 = null; // warn 3 string? ns3 = FalseNMethod(); ns3 /*T:string?*/ .ToString(); // warn 4 ns3 = null; var s4 = Method(); s4 /*T:string!*/ .ToString(); s4 = null; // warn 5 var ns4 = NMethod(); ns4 /*T:string?*/ .ToString(); // warn 6 ns4 = null; var s5 = FalseMethod(); s5 /*T:string!*/ .ToString(); s5 = null; var ns5 = FalseNMethod(); ns5 /*T:string?*/ .ToString(); // warn 7 ns5 = null; } } public class Base { #nullable enable public string Method() => throw null!; #nullable enable public string? NMethod() => throw null!; #nullable disable public string FalseMethod() => throw null!; #nullable disable public string? FalseNMethod() => throw null!; // warn 8 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (54,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public string? FalseNMethod() => throw null!; // warn 8 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(54, 18), // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s2 = null; // warn 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 14), // (14,9): warning CS8602: Dereference of a possibly null reference. // ns2 /*T:string?*/ .ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns2").WithLocation(14, 9), // (19,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s3 = null; // warn 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(19, 14), // (22,9): warning CS8602: Dereference of a possibly null reference. // ns3 /*T:string?*/ .ToString(); // warn 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns3").WithLocation(22, 9), // (27,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s4 = null; // warn 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(27, 14), // (30,9): warning CS8602: Dereference of a possibly null reference. // ns4 /*T:string?*/ .ToString(); // warn 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns4").WithLocation(30, 9), // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s5 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(35, 14), // (38,9): warning CS8602: Dereference of a possibly null reference. // ns5 /*T:string?*/ .ToString(); // warn 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ns5").WithLocation(38, 9) ); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void NonNullTypesFalse_LocalDeclarations() { var source = @" #nullable disable public class C : Base { public void M() { string s2 = Method(); s2 /*T:string!*/ .ToString(); s2 = null; string? ns2 = NMethod(); // 1 ns2 /*T:string?*/ .ToString(); ns2 = null; string s3 = FalseMethod(); s3 /*T:string!*/ .ToString(); s3 = null; string? ns3 = FalseNMethod(); // 2 ns3 /*T:string?*/ .ToString(); ns3 = null; var s4 = Method(); s4 /*T:string!*/ .ToString(); s4 = null; var ns4 = NMethod(); ns4 /*T:string?*/ .ToString(); ns4 = null; var s5 = FalseMethod(); s5 /*T:string!*/ .ToString(); s5 = null; var ns5 = FalseNMethod(); ns5 /*T:string?*/ .ToString(); ns5 = null; } } public class Base { #nullable enable public string Method() => throw null!; #nullable enable public string? NMethod() => throw null!; #nullable disable public string FalseMethod() => throw null!; #nullable disable public string? FalseNMethod() => throw null!; // 3 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (54,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public string? FalseNMethod() => throw null!; // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(54, 18), // (13,15): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? ns2 = NMethod(); // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 15), // (21,15): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? ns3 = FalseNMethod(); // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 15) ); } [Fact] public void NonNullTypes_Constraint() { var source = @" public class S { } #nullable enable public struct C where T : S { public void M(T t) { t.ToString(); t = null; // warn } } #nullable disable public struct D where T : S { public void M(T t) { t.ToString(); t = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (11,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // t = null; // warn Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 13) ); } [Fact] public void NonNullTypes_Delegate() { var source = @" #nullable enable public delegate string[] MyDelegate(string[] x); #nullable disable public delegate string[] MyFalseDelegate(string[] x); #nullable enable public delegate string[]? MyNullableDelegate(string[]? x); class C { void M() { MyDelegate x1 = Method; MyDelegate x2 = FalseMethod; MyDelegate x4 = NullableReturnMethod; // warn 1 MyDelegate x5 = NullableParameterMethod; MyFalseDelegate y1 = Method; MyFalseDelegate y2 = FalseMethod; MyFalseDelegate y4 = NullableReturnMethod; MyFalseDelegate y5 = NullableParameterMethod; MyNullableDelegate z1 = Method; // warn 2 MyNullableDelegate z2 = FalseMethod; MyNullableDelegate z4 = NullableReturnMethod; // warn 3 MyNullableDelegate z5 = NullableParameterMethod; } #nullable enable public string[] Method(string[] x) => throw null!; #nullable disable public string[] FalseMethod(string[] x) => throw null!; #nullable enable public string[]? NullableReturnMethod(string[] x) => throw null!; public string[] NullableParameterMethod(string[]? x) => throw null!; } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (18,25): warning CS8621: Nullability of reference types in return type of 'string[]? C.NullableReturnMethod(string[] x)' doesn't match the target delegate 'MyDelegate'. // MyDelegate x4 = NullableReturnMethod; // warn 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "NullableReturnMethod").WithArguments("string[]? C.NullableReturnMethod(string[] x)", "MyDelegate").WithLocation(18, 25), // (24,33): warning CS8622: Nullability of reference types in type of parameter 'x' of 'string[] C.Method(string[] x)' doesn't match the target delegate 'MyNullableDelegate'. // MyNullableDelegate z1 = Method; // warn 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "Method").WithArguments("x", "string[] C.Method(string[] x)", "MyNullableDelegate").WithLocation(24, 33), // (26,33): warning CS8622: Nullability of reference types in type of parameter 'x' of 'string[]? C.NullableReturnMethod(string[] x)' doesn't match the target delegate 'MyNullableDelegate'. // MyNullableDelegate z4 = NullableReturnMethod; // warn 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "NullableReturnMethod").WithArguments("x", "string[]? C.NullableReturnMethod(string[] x)", "MyNullableDelegate").WithLocation(26, 33) ); } [Fact] public void NonNullTypes_Constructor() { var source = @" public class C { #nullable enable public C(string[] x) => throw null!; } public class D { #nullable disable public D(string[] x) => throw null!; } #nullable enable public class E { public string[] field = null!; #nullable disable public string[] obliviousField; #nullable enable public string[]? nullableField; void M() { new C(field); new C(obliviousField); new C(nullableField); // warn new D(field); new D(obliviousField); new D(nullableField); } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (27,15): warning CS8604: Possible null reference argument for parameter 'x' in 'C.C(string[] x)'. // new C(nullableField); // warn Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nullableField").WithArguments("x", "C.C(string[] x)").WithLocation(27, 15) ); } [Fact] public void NonNullTypes_Constraint_Nested() { var source = @" public class S { } public class List { public T Item { get; set; } = default!; } #nullable enable public struct C where T : List where NT : List { public void M(T t, NT nt) { t.Item /*T:S!*/ .ToString(); t.Item = null; // warn 1 nt.Item /*T:S?*/ .ToString(); // warn 2 nt.Item = null; } } #nullable disable public struct D where T : List where NT : List // warn 3 { public void M(T t, NT nt) { t.Item /*T:S!*/ .ToString(); t.Item = null; nt.Item /*T:S?*/ .ToString(); nt.Item = null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyTypes(); compilation.VerifyDiagnostics( // (14,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // t.Item = null; // warn 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 18), // (15,9): warning CS8602: Dereference of a possibly null reference. // nt.Item /*T:S?*/ .ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "nt.Item").WithLocation(15, 9), // (23,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // where NT : List // warn 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 22)); } [Fact] public void IsAnnotated_01() { var source = @"using System; class C1 { string F1() => throw null!; string? F2() => throw null!; int F3() => throw null!; int? F4() => throw null!; Nullable F5() => throw null!; } #nullable disable class C2 { string F1() => throw null!; string? F2() => throw null!; int F3() => throw null!; int? F4() => throw null!; Nullable F5() => throw null!; } #nullable enable class C3 { string F1() => throw null!; string? F2() => throw null!; int F3() => throw null!; int? F4() => throw null!; Nullable F5() => throw null!; }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (6,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? F2() => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 11), // (15,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string? F2() => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 11) ); verify("C1.F1", "System.String", NullableAnnotation.Oblivious); verify("C1.F2", "System.String?", NullableAnnotation.Annotated); verify("C1.F3", "System.Int32", NullableAnnotation.Oblivious); verify("C1.F4", "System.Int32?", NullableAnnotation.Annotated); verify("C1.F5", "System.Int32?", NullableAnnotation.Annotated); verify("C2.F1", "System.String", NullableAnnotation.Oblivious); verify("C2.F2", "System.String?", NullableAnnotation.Annotated); verify("C2.F3", "System.Int32", NullableAnnotation.Oblivious); verify("C2.F4", "System.Int32?", NullableAnnotation.Annotated); verify("C2.F5", "System.Int32?", NullableAnnotation.Annotated); verify("C3.F1", "System.String!", NullableAnnotation.NotAnnotated); verify("C3.F2", "System.String?", NullableAnnotation.Annotated); verify("C3.F3", "System.Int32", NullableAnnotation.NotAnnotated); verify("C3.F4", "System.Int32?", NullableAnnotation.Annotated); verify("C3.F5", "System.Int32?", NullableAnnotation.Annotated); // https://github.com/dotnet/roslyn/issues/29845: Test nested nullability. void verify(string methodName, string displayName, NullableAnnotation nullableAnnotation) { var method = comp.GetMember(methodName); var type = method.ReturnTypeWithAnnotations; Assert.Equal(displayName, type.ToTestDisplayString(true)); Assert.Equal(nullableAnnotation, type.NullableAnnotation); } } [Fact] public void IsAnnotated_02() { var source = @"using System; class C1 { T F1() => throw null!; T? F2() => throw null!; T F3() where T : class => throw null!; T? F4() where T : class => throw null!; T F5() where T : struct => throw null!; T? F6() where T : struct => throw null!; Nullable F7() where T : struct => throw null!; } #nullable disable class C2 { T F1() => throw null!; T? F2() => throw null!; T F3() where T : class => throw null!; T? F4() where T : class => throw null!; T F5() where T : struct => throw null!; T? F6() where T : struct => throw null!; Nullable F7() where T : struct => throw null!; } #nullable enable class C3 { T F1() => throw null!; T? F2() => throw null!; T F3() where T : class => throw null!; T? F4() where T : class => throw null!; T F5() where T : struct => throw null!; T? F6() where T : struct => throw null!; Nullable F7() where T : struct => throw null!; }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (6,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? F2() => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(6, 5), // (6,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? F2() => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 6), // (8,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? F4() where T : class => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 6), // (8,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? F4() where T : class => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 5), // (17,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? F2() => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(17, 5), // (28,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? F2() => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(28, 5), // (17,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? F2() => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 6), // (19,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? F4() where T : class => throw null!; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 6), // (19,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? F4() where T : class => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(19, 5) ); verify("C1.F1", "T", NullableAnnotation.Oblivious); verify("C1.F2", "T?", NullableAnnotation.Annotated); verify("C1.F3", "T", NullableAnnotation.Oblivious); verify("C1.F4", "T?", NullableAnnotation.Annotated); verify("C1.F5", "T", NullableAnnotation.Oblivious); verify("C1.F6", "T?", NullableAnnotation.Annotated); verify("C1.F7", "T?", NullableAnnotation.Annotated); verify("C2.F1", "T", NullableAnnotation.Oblivious); verify("C2.F2", "T?", NullableAnnotation.Annotated); verify("C2.F3", "T", NullableAnnotation.Oblivious); verify("C2.F4", "T?", NullableAnnotation.Annotated); verify("C2.F5", "T", NullableAnnotation.Oblivious); verify("C2.F6", "T?", NullableAnnotation.Annotated); verify("C2.F7", "T?", NullableAnnotation.Annotated); verify("C3.F1", "T", NullableAnnotation.NotAnnotated); verify("C3.F2", "T?", NullableAnnotation.Annotated); verify("C3.F3", "T!", NullableAnnotation.NotAnnotated); verify("C3.F4", "T?", NullableAnnotation.Annotated); verify("C3.F5", "T", NullableAnnotation.NotAnnotated); verify("C3.F6", "T?", NullableAnnotation.Annotated); verify("C3.F7", "T?", NullableAnnotation.Annotated); // https://github.com/dotnet/roslyn/issues/29845: Test nested nullability. // https://github.com/dotnet/roslyn/issues/29845: Test all combinations of overrides. void verify(string methodName, string displayName, NullableAnnotation nullableAnnotation) { var method = comp.GetMember(methodName); var type = method.ReturnTypeWithAnnotations; Assert.Equal(displayName, type.ToTestDisplayString(true)); Assert.Equal(nullableAnnotation, type.NullableAnnotation); } } [Fact] public void InheritedValueConstraintForNullable1_01() { var source = @" class A { public virtual T? Goo() where T : struct { return null; } } class B : A { public override T? Goo() { return null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); //var a = compilation.GetTypeByMetadataName("A"); //var aGoo = a.GetMember("Goo"); //Assert.Equal("T? A.Goo()", aGoo.ToTestDisplayString()); //var b = compilation.GetTypeByMetadataName("B"); //var bGoo = b.GetMember("Goo"); //Assert.Equal("T? A.Goo()", bGoo.OverriddenMethod.ToTestDisplayString()); compilation.VerifyDiagnostics(); } [Fact] public void InheritedValueConstraintForNullable1_02() { var source = @" class A { public virtual void Goo(T? x) where T : struct { } } class B : A { public override void Goo(T? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); } [Fact] public void InheritedValueConstraintForNullable1_03() { var source = @" class A { public virtual System.Nullable Goo() where T : struct { return null; } } class B : A { public override T? Goo() { return null; } } "; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void InheritedValueConstraintForNullable1_04() { var source = @" class A { public virtual void Goo(System.Nullable x) where T : struct { } } class B : A { public override void Goo(T? x) { } } "; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void InheritedValueConstraintForNullable1_05() { var source = @" class A { public virtual T? Goo() where T : struct { return null; } } class B : A { public override System.Nullable Goo() { return null; } } "; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void InheritedValueConstraintForNullable1_06() { var source = @" class A { public virtual void M1(T? x) where T : struct { } } class B : A { public override void M1(System.Nullable x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.True(m1.Parameters[0].Type.IsValueType); Assert.True(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); } [Fact] public void Overriding_03() { var source = @" class A { public virtual void M1(T? x) where T : class { } public virtual T? M2() where T : class { return null; } } class B : A { public override void M1(T? x) { } public override T? M2() { return null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (16,26): error CS0115: 'B.M1(T?)': no suitable method found to override // public override void M1(T? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M1").WithArguments("B.M1(T?)").WithLocation(16, 26), // (16,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M1(T? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(16, 35), // (20,24): error CS0508: 'B.M2()': return type must be 'T' to match overridden member 'A.M2()' // public override T? M2() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M2").WithArguments("B.M2()", "A.M2()", "T").WithLocation(20, 24), // (20,24): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override T? M2() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M2").WithArguments("System.Nullable", "T", "T").WithLocation(20, 24)); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.False(m1.Parameters[0].Type.IsReferenceType); Assert.Null(m1.OverriddenMethod); var m2 = b.GetMember("M2"); Assert.True(m2.ReturnType.IsNullableType()); Assert.False(m2.ReturnType.IsReferenceType); Assert.False(m2.OverriddenMethod.ReturnType.IsNullableType()); } [Fact] [WorkItem(29846, "https://github.com/dotnet/roslyn/issues/29846")] public void Overriding_04() { var source = @" class A { public virtual void M1(T? x) where T : struct { } public virtual void M1(T x) { } public virtual void M2(T? x) where T : struct { } public virtual void M2(T x) { } public virtual void M3(T x) { } public virtual void M3(T? x) where T : struct { } } class B : A { public override void M1(T? x) { } public override void M2(T x) { } public override void M3(T? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.True(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); var m2 = b.GetMember("M2"); Assert.False(m2.Parameters[0].Type.IsNullableType()); Assert.False(m2.OverriddenMethod.Parameters[0].Type.IsNullableType()); var m3 = b.GetMember("M3"); Assert.True(m3.Parameters[0].Type.IsNullableType()); Assert.True(m3.OverriddenMethod.Parameters[0].Type.IsNullableType()); } [Fact] [WorkItem(29847, "https://github.com/dotnet/roslyn/issues/29847")] public void Overriding_05() { var source = @" class A { public virtual void M1(T? x) where T : struct { } public virtual void M1(T? x) where T : class { } } class B : A { public override void M1(T? x) { } } class C { public virtual void M2(T? x) where T : class { } public virtual void M2(T? x) where T : struct { } } class D : C { public override void M2(T? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.True(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); var d = compilation.GetTypeByMetadataName("D"); var m2 = d.GetMember("M2"); Assert.True(m2.Parameters[0].Type.IsNullableType()); Assert.True(m2.OverriddenMethod.Parameters[0].Type.IsNullableType()); } [Fact] public void Overriding_06() { var source = @" class A { public virtual void M1(System.Nullable x) where T : struct { } public virtual void M2(T? x) where T : struct { } public virtual void M3(C x) where T : struct { } public virtual void M4(C> x) where T : struct { } public virtual void M5(C x) where T : class { } } class B : A { public override void M1(T? x) { } public override void M2(T? x) { } public override void M3(C x) { } public override void M4(C x) { } public override void M5(C x) { } } class C {} "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (43,26): error CS0115: 'B.M5(C)': no suitable method found to override // public override void M5(C x) where T : class Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M5").WithArguments("B.M5(C)").WithLocation(43, 26), // (43,38): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M5(C x) where T : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(43, 38)); var b = compilation.GetTypeByMetadataName("B"); var m3 = b.GetMember("M3"); var m4 = b.GetMember("M4"); var m5 = b.GetMember("M5"); Assert.True(((NamedTypeSymbol)m3.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m3.OverriddenMethod.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m4.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m4.OverriddenMethod.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m5.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.Null(m5.OverriddenMethod); } [Fact] public void Overriding_07() { var source = @" class A { public void M1(T x) { } } class B : A { public void M1(T? x) where T : struct { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.True(m1.Parameters[0].Type.StrippedType().IsValueType); Assert.Null(m1.OverriddenMethod); } [Fact] public void Overriding_08() { var source = @" class A { public void M1(T x) { } } class B : A { public override void M1(T? x) where T : struct { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (11,26): error CS0115: 'B.M1(T?)': no suitable method found to override // public override void M1(T? x) where T : struct Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M1").WithArguments("B.M1(T?)").WithLocation(11, 26), // (11,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M1(T? x) where T : struct Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(11, 35) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.False(m1.Parameters[0].Type.StrippedType().IsValueType); Assert.False(m1.Parameters[0].Type.StrippedType().IsReferenceType); Assert.Null(m1.OverriddenMethod); } [Fact] public void Overriding_09() { var source = @" class A { public void M1(T x) { } public void M2(T? x) { } public void M3(T? x) where T : class { } public void M4(T? x) where T : struct { } } class B : A { public override void M1(T? x) { } public override void M2(T? x) { } public override void M3(T? x) { } public override void M4(T? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (8,23): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void M2(T? x) Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 23), // (27,26): error CS0115: 'B.M2(T?)': no suitable method found to override // public override void M2(T? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M2").WithArguments("B.M2(T?)").WithLocation(27, 26), // (31,26): error CS0115: 'B.M3(T?)': no suitable method found to override // public override void M3(T? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M3").WithArguments("B.M3(T?)").WithLocation(31, 26), // (35,26): error CS0506: 'B.M4(T?)': cannot override inherited member 'A.M4(T?)' because it is not marked virtual, abstract, or override // public override void M4(T? x) Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "M4").WithArguments("B.M4(T?)", "A.M4(T?)").WithLocation(35, 26), // (23,26): error CS0115: 'B.M1(T?)': no suitable method found to override // public override void M1(T? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M1").WithArguments("B.M1(T?)").WithLocation(23, 26), // (27,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M2(T? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(27, 35), // (31,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M3(T? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(31, 35), // (35,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M4(T? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(35, 35), // (23,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M1(T? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(23, 35) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); var m2 = b.GetMember("M2"); var m3 = b.GetMember("M3"); var m4 = b.GetMember("M4"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.True(m2.Parameters[0].Type.IsNullableType()); Assert.True(m3.Parameters[0].Type.IsNullableType()); Assert.True(m4.Parameters[0].Type.IsNullableType()); Assert.Null(m1.OverriddenMethod); Assert.Null(m2.OverriddenMethod); Assert.Null(m3.OverriddenMethod); Assert.Null(m4.OverriddenMethod); } [Fact] public void Overriding_10() { var source = @" class A { public virtual void M1(System.Nullable x) where T : class { } } class B : A { public override void M1(T? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (4,50): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public virtual void M1(System.Nullable x) where T : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(4, 50), // (11,35): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M1(T? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(11, 35) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.NotNull(m1.OverriddenMethod); } [Fact] public void Overriding_11() { var source = @" class A { public virtual C> M1() where T : class { throw new System.NotImplementedException(); } } class B : A { public override C M1() { throw new System.NotImplementedException(); } } class C {} "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (4,42): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public virtual C> M1() where T : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M1").WithArguments("System.Nullable", "T", "T").WithLocation(4, 42), // (12,27): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override C M1() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M1").WithArguments("System.Nullable", "T", "T").WithLocation(12, 27) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(((NamedTypeSymbol)m1.ReturnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m1.OverriddenMethod.ReturnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); } [Fact] public void Overriding_12() { var source = @" class A { public virtual string M1() { throw new System.NotImplementedException(); } public virtual string? M2() { throw new System.NotImplementedException(); } public virtual string? M3() { throw new System.NotImplementedException(); } public virtual System.Nullable M4() { throw new System.NotImplementedException(); } public System.Nullable M5() { throw new System.NotImplementedException(); } } class B : A { public override string? M1() { throw new System.NotImplementedException(); } public override string? M2() { throw new System.NotImplementedException(); } public override string M3() { throw new System.NotImplementedException(); } public override string? M4() { throw new System.NotImplementedException(); } public override string? M5() { throw new System.NotImplementedException(); } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (47,29): error CS0508: 'B.M4()': return type must be 'string?' to match overridden member 'A.M4()' // public override string? M4() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M4").WithArguments("B.M4()", "A.M4()", "string?").WithLocation(47, 29), // (52,29): error CS0506: 'B.M5()': cannot override inherited member 'A.M5()' because it is not marked virtual, abstract, or override // public override string? M5() Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "M5").WithArguments("B.M5()", "A.M5()").WithLocation(52, 29), // (32,29): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override string? M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(32, 29), // (19,44): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public virtual System.Nullable M4() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M4").WithArguments("System.Nullable", "T", "string").WithLocation(19, 44), // (24,36): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public System.Nullable M5() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M5").WithArguments("System.Nullable", "T", "string").WithLocation(24, 36) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.False(m1.ReturnType.IsNullableType()); Assert.False(m1.OverriddenMethod.ReturnType.IsNullableType()); var m4 = b.GetMember("M4"); Assert.False(m4.ReturnType.IsNullableType()); Assert.True(m4.OverriddenMethod.ReturnType.IsNullableType()); var m5 = b.GetMember("M4"); Assert.False(m5.ReturnType.IsNullableType()); } [Fact] public void Overriding_13() { var source = @" class A { public virtual void M1(string x) { } public virtual void M2(string? x) { } public virtual void M3(string? x) { } public virtual void M4(System.Nullable x) { } public void M5(System.Nullable x) { } } class B : A { public override void M1(string? x) { } public override void M2(string? x) { } public override void M3(string x) { } public override void M4(string? x) { } public override void M5(string? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (16,52): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public virtual void M4(System.Nullable x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "string").WithLocation(16, 52), // (20,44): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public void M5(System.Nullable x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "string").WithLocation(20, 44), // (35,26): warning CS8610: Nullability of reference types in type of parameter 'x' doesn't match overridden member. // public override void M3(string x) Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M3").WithArguments("x").WithLocation(35, 26), // (39,26): error CS0115: 'B.M4(string?)': no suitable method found to override // public override void M4(string? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M4").WithArguments("B.M4(string?)").WithLocation(39, 26), // (43,26): error CS0115: 'B.M5(string?)': no suitable method found to override // public override void M5(string? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M5").WithArguments("B.M5(string?)").WithLocation(43, 26) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.False(m1.Parameters[0].Type.IsNullableType()); Assert.Equal(NullableAnnotation.Annotated, m1.Parameters[0].TypeWithAnnotations.NullableAnnotation); Assert.True(m1.Parameters[0].Type.IsReferenceType); Assert.False(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); var m4 = b.GetMember("M4"); Assert.False(m4.Parameters[0].Type.IsNullableType()); Assert.Null(m4.OverriddenMethod); var m5 = b.GetMember("M4"); Assert.False(m5.Parameters[0].Type.IsNullableType()); } [Fact] public void Overriding_14() { var source = @" class A { public virtual int M1() { throw new System.NotImplementedException(); } public virtual int? M2() { throw new System.NotImplementedException(); } public virtual int? M3() { throw new System.NotImplementedException(); } public virtual System.Nullable M4() { throw new System.NotImplementedException(); } public System.Nullable M5() { throw new System.NotImplementedException(); } } class B : A { public override int? M1() { throw new System.NotImplementedException(); } public override int? M2() { throw new System.NotImplementedException(); } public override int M3() { throw new System.NotImplementedException(); } public override int? M4() { throw new System.NotImplementedException(); } public override int? M5() { throw new System.NotImplementedException(); } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (42,25): error CS0508: 'B.M3()': return type must be 'int?' to match overridden member 'A.M3()' // public override int M3() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M3").WithArguments("B.M3()", "A.M3()", "int?").WithLocation(42, 25), // (52,26): error CS0506: 'B.M5()': cannot override inherited member 'A.M5()' because it is not marked virtual, abstract, or override // public override int? M5() Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "M5").WithArguments("B.M5()", "A.M5()").WithLocation(52, 26), // (32,26): error CS0508: 'B.M1()': return type must be 'int' to match overridden member 'A.M1()' // public override int? M1() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M1").WithArguments("B.M1()", "A.M1()", "int").WithLocation(32, 26) ); var b = compilation.GetTypeByMetadataName("B"); Assert.True(b.GetMember("M1").ReturnType.IsNullableType()); Assert.True(b.GetMember("M2").ReturnType.IsNullableType()); Assert.False(b.GetMember("M3").ReturnType.IsNullableType()); Assert.True(b.GetMember("M4").ReturnType.IsNullableType()); Assert.True(b.GetMember("M5").ReturnType.IsNullableType()); } [Fact] public void Overriding_15() { var source = @" class A { public virtual void M1(int x) { } public virtual void M2(int? x) { } public virtual void M3(int? x) { } public virtual void M4(System.Nullable x) { } public void M5(System.Nullable x) { } } class B : A { public override void M1(int? x) { } public override void M2(int? x) { } public override void M3(int x) { } public override void M4(int? x) { } public override void M5(int? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (35,26): error CS0115: 'B.M3(int)': no suitable method found to override // public override void M3(int x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M3").WithArguments("B.M3(int)").WithLocation(35, 26), // (43,26): error CS0506: 'B.M5(int?)': cannot override inherited member 'A.M5(int?)' because it is not marked virtual, abstract, or override // public override void M5(int? x) Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "M5").WithArguments("B.M5(int?)", "A.M5(int?)").WithLocation(43, 26), // (27,26): error CS0115: 'B.M1(int?)': no suitable method found to override // public override void M1(int? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M1").WithArguments("B.M1(int?)").WithLocation(27, 26) ); var b = compilation.GetTypeByMetadataName("B"); Assert.True(b.GetMember("M1").Parameters[0].Type.IsNullableType()); Assert.True(b.GetMember("M2").Parameters[0].Type.IsNullableType()); Assert.False(b.GetMember("M3").Parameters[0].Type.IsNullableType()); Assert.True(b.GetMember("M4").Parameters[0].Type.IsNullableType()); Assert.True(b.GetMember("M5").Parameters[0].Type.IsNullableType()); } [Fact] public void Overriding_16() { var source = @" class C { public static void Main() { } } abstract class A { public abstract event System.Action E1; public abstract event System.Action? E2; public abstract event System.Action? E3; } class B1 : A { public override event System.Action E1 {add {} remove{}} public override event System.Action E2 {add {} remove{}} public override event System.Action? E3 {add {} remove{}} } class B2 : A { public override event System.Action E1; // 2 public override event System.Action E2; // 2 public override event System.Action? E3; // 2 void Dummy() { var e1 = E1; var e2 = E2; var e3 = E3; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (18,50): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event System.Action E1 {add {} remove{}} Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E1").WithLocation(18, 50), // (19,49): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event System.Action E2 {add {} remove{}} Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E2").WithLocation(19, 49), // (25,50): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event System.Action E1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E1").WithLocation(25, 50), // (26,49): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event System.Action E2; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E2").WithLocation(26, 49) ); foreach (string typeName in new[] { "B1", "B2" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (string memberName in new[] { "E1", "E2" }) { var member = type.GetMember(memberName); Assert.False(member.TypeWithAnnotations.Equals(member.OverriddenEvent.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } var e3 = type.GetMember("E3"); Assert.True(e3.TypeWithAnnotations.Equals(e3.OverriddenEvent.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "A", "B1", "B2" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var ev in type.GetMembers().OfType()) { Assert.True(ev.TypeWithAnnotations.Equals(ev.AddMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(ev.TypeWithAnnotations.Equals(ev.RemoveMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] [WorkItem(29851, "https://github.com/dotnet/roslyn/issues/29851")] public void Overriding_Methods() { var source = @" public abstract class A { #nullable disable public abstract System.Action Oblivious1(System.Action x); #nullable enable public abstract System.Action Oblivious2(System.Action x); public abstract System.Action M3(System.Action x); public abstract System.Action M4(System.Action x); public abstract System.Action? M5(System.Action? x); } public class B1 : A { public override System.Action Oblivious1(System.Action x) => throw null!; public override System.Action Oblivious2(System.Action x) => throw null!; // warn 3 and 4 // https://github.com/dotnet/roslyn/issues/29851: Should not warn public override System.Action M3(System.Action x) => throw null!; // warn 5 and 6 public override System.Action M4(System.Action x) => throw null!; // warn 7 and 8 public override System.Action M5(System.Action x) => throw null!; // warn 9 and 10 } public class B2 : A { public override System.Action Oblivious1(System.Action x) => throw null!; public override System.Action Oblivious2(System.Action x) => throw null!; #nullable disable public override System.Action M3(System.Action x) => throw null!; #nullable enable public override System.Action M4(System.Action x) => throw null!; #nullable disable public override System.Action M5(System.Action x) => throw null!; } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (18,44): warning CS8610: Nullability of reference types in type of parameter 'x' doesn't match overridden member. // public override System.Action Oblivious2(System.Action x) => throw null!; // warn 3 and 4 // https://github.com/dotnet/roslyn/issues/29851: Should not warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "Oblivious2").WithArguments("x").WithLocation(18, 44), // (19,44): warning CS8610: Nullability of reference types in type of parameter 'x' doesn't match overridden member. // public override System.Action M3(System.Action x) => throw null!; // warn 5 and 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M3").WithArguments("x").WithLocation(19, 44), // (20,44): warning CS8610: Nullability of reference types in type of parameter 'x' doesn't match overridden member. // public override System.Action M4(System.Action x) => throw null!; // warn 7 and 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M4").WithArguments("x").WithLocation(20, 44), // (21,44): warning CS8610: Nullability of reference types in type of parameter 'x' doesn't match overridden member. // public override System.Action M5(System.Action x) => throw null!; // warn 9 and 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M5").WithArguments("x").WithLocation(21, 44) ); var b1 = compilation.GetTypeByMetadataName("B1"); verifyMethodMatchesOverridden(expectMatch: false, b1, "Oblivious1"); verifyMethodMatchesOverridden(expectMatch: false, b1, "Oblivious2"); verifyMethodMatchesOverridden(expectMatch: false, b1, "M3"); verifyMethodMatchesOverridden(expectMatch: false, b1, "M4"); verifyMethodMatchesOverridden(expectMatch: false, b1, "M5"); var b2 = compilation.GetTypeByMetadataName("B2"); verifyMethodMatchesOverridden(expectMatch: false, b2, "Oblivious1"); // https://github.com/dotnet/roslyn/issues/29851: They should match verifyMethodMatchesOverridden(expectMatch: true, b2, "Oblivious2"); // https://github.com/dotnet/roslyn/issues/29851: They should not match verifyMethodMatchesOverridden(expectMatch: false, b2, "M3"); verifyMethodMatchesOverridden(expectMatch: true, b2, "M4"); // https://github.com/dotnet/roslyn/issues/29851: They should not match verifyMethodMatchesOverridden(expectMatch: false, b2, "M5"); void verifyMethodMatchesOverridden(bool expectMatch, NamedTypeSymbol type, string methodName) { var member = type.GetMember(methodName); Assert.Equal(expectMatch, member.ReturnTypeWithAnnotations.Equals(member.OverriddenMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.Equal(expectMatch, member.Parameters.Single().TypeWithAnnotations.Equals(member.OverriddenMethod.Parameters.Single().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } [Fact] public void Overriding_Properties_WithNullableTypeArgument() { var source = @" #nullable enable public class List { } public class Base { public virtual List P { get; set; } = default; } public class Class : Base { #nullable disable public override List P { get; set; } = default; } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (7,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public virtual List P { get; set; } = default; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 25), // (7,47): warning CS8625: Cannot convert null literal to non-nullable reference type. // public virtual List P { get; set; } = default; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(7, 47), // (12,26): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public override List P { get; set; } = default; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(12, 26), // (12,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override List P { get; set; } = default; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(12, 27) ); } [Fact] public void Overriding_Properties_WithNullableTypeArgument_WithClassConstraint() { var source = @" #nullable enable public class List { } public class Base where T : class { public virtual List P { get; set; } = default; } public class Class : Base where T : class { #nullable disable public override List P { get; set; } = default; } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (7,47): warning CS8625: Cannot convert null literal to non-nullable reference type. // public virtual List P { get; set; } = default; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(7, 47), // (12,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override List P { get; set; } = default; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(12, 27) ); } [Fact] public void Overriding_Properties_WithNullableTypeArgument_WithStructConstraint() { var source = @" public class List { } public class Base where T : struct { public virtual List P { get; set; } = default; } public class Class : Base where T : struct { #nullable disable public override List P { get; set; } = default; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,47): warning CS8625: Cannot convert null literal to non-nullable reference type. // public virtual List P { get; set; } = default; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(6, 47)); } [Fact] public void Overriding_Indexer() { var source = @" public class List { } public class Base { public virtual List this[List x] { get => throw null!; set => throw null!; } } public class Class : Base { #nullable disable public override List this[List x] { get => throw null!; set => throw null!; } } public class Class2 : Base { #nullable enable public override List this[List x] { get => throw null!; set => throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Overriding_Indexer2() { var source = @" #nullable enable public class List { } public class Oblivious { #nullable disable public virtual List this[List x] { get => throw null!; set => throw null!; } } #nullable enable public class Class : Oblivious { public override List this[List x] { get => throw null!; set => throw null!; } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); } [Fact] public void Overriding_21() { var source = @" class C { public static void Main() { } } abstract class A { public abstract event System.Action E1; public abstract event System.Action? E2; } class B1 : A { #nullable disable public override event System.Action E1 {add {} remove{}} // 1 #nullable disable public override event System.Action E2 {add {} remove{}} } #nullable enable class B2 : A { #nullable disable public override event System.Action E1; // 3 #nullable disable public override event System.Action E2; #nullable enable void Dummy() { var e1 = E1; var e2 = E2; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (19,47): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override event System.Action E1 {add {} remove{}} // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 47), // (19,50): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event System.Action E1 {add {} remove{}} // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E1").WithLocation(19, 50), // (27,47): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override event System.Action E1; // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(27, 47), // (27,50): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event System.Action E1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E1").WithLocation(27, 50) ); } [Fact] public void Implementing_01() { var source = @" class C { public static void Main() { } } interface IA { event System.Action E1; event System.Action? E2; event System.Action? E3; } class B1 : IA { public event System.Action E1 {add {} remove{}} public event System.Action E2 {add {} remove{}} public event System.Action? E3 {add {} remove{}} } class B2 : IA { public event System.Action E1; // 2 public event System.Action E2; // 2 public event System.Action? E3; // 2 void Dummy() { var e1 = E1; var e2 = E2; var e3 = E3; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (26,40): warning CS8612: Nullability of reference types in type of 'event Action B2.E2' doesn't match implicitly implemented member 'event Action? IA.E2'. // public event System.Action E2; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "E2").WithArguments("event Action B2.E2", "event Action? IA.E2").WithLocation(26, 40), // (25,41): warning CS8612: Nullability of reference types in type of 'event Action B2.E1' doesn't match implicitly implemented member 'event Action IA.E1'. // public event System.Action E1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "E1").WithArguments("event Action B2.E1", "event Action IA.E1").WithLocation(25, 41), // (19,40): warning CS8612: Nullability of reference types in type of 'event Action B1.E2' doesn't match implicitly implemented member 'event Action? IA.E2'. // public event System.Action E2 {add {} remove{}} Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "E2").WithArguments("event Action B1.E2", "event Action? IA.E2").WithLocation(19, 40), // (18,41): warning CS8612: Nullability of reference types in type of 'event Action B1.E1' doesn't match implicitly implemented member 'event Action IA.E1'. // public event System.Action E1 {add {} remove{}} Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "E1").WithArguments("event Action B1.E1", "event Action IA.E1").WithLocation(18, 41) ); var ia = compilation.GetTypeByMetadataName("IA"); foreach (string memberName in new[] { "E1", "E2" }) { var member = ia.GetMember(memberName); foreach (string typeName in new[] { "B1", "B2" }) { var type = compilation.GetTypeByMetadataName(typeName); var impl = (EventSymbol)type.FindImplementationForInterfaceMember(member); Assert.False(impl.TypeWithAnnotations.Equals(member.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } var e3 = ia.GetMember("E3"); foreach (string typeName in new[] { "B1", "B2" }) { var type = compilation.GetTypeByMetadataName(typeName); var impl = (EventSymbol)type.FindImplementationForInterfaceMember(e3); Assert.True(impl.TypeWithAnnotations.Equals(e3.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "IA", "B1", "B2" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var ev in type.GetMembers().OfType()) { Assert.True(ev.TypeWithAnnotations.Equals(ev.AddMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(ev.TypeWithAnnotations.Equals(ev.RemoveMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Implementing_02() { var source = @" class C { public static void Main() { } } interface IA { event System.Action E1; event System.Action? E2; event System.Action? E3; } class B1 : IA { event System.Action IA.E1 {add {} remove{}} event System.Action IA.E2 {add {} remove{}} event System.Action? IA.E3 {add {} remove{}} } interface IB { //event System.Action E1; //event System.Action? E2; event System.Action? E3; } class B2 : IB { //event System.Action IB.E1; // 2 //event System.Action IB.E2; // 2 event System.Action? IB.E3; // 2 } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (34,38): error CS0071: An explicit interface implementation of an event must use event accessor syntax // event System.Action? IB.E3; // 2 Diagnostic(ErrorCode.ERR_ExplicitEventFieldImpl, "E3").WithLocation(34, 38), // (30,12): error CS0535: 'B2' does not implement interface member 'IB.E3.remove' // class B2 : IB Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IB").WithArguments("B2", "IB.E3.remove").WithLocation(30, 12), // (30,12): error CS0535: 'B2' does not implement interface member 'IB.E3.add' // class B2 : IB Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IB").WithArguments("B2", "IB.E3.add").WithLocation(30, 12), // (19,36): warning CS8615: Nullability of reference types in type doesn't match implemented member 'event Action? IA.E2'. // event System.Action IA.E2 {add {} remove{}} Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation, "E2").WithArguments("event Action? IA.E2").WithLocation(19, 36), // (18,37): warning CS8615: Nullability of reference types in type doesn't match implemented member 'event Action IA.E1'. // event System.Action IA.E1 {add {} remove{}} Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation, "E1").WithArguments("event Action IA.E1").WithLocation(18, 37) ); var ia = compilation.GetTypeByMetadataName("IA"); var b1 = compilation.GetTypeByMetadataName("B1"); foreach (string memberName in new[] { "E1", "E2" }) { var member = ia.GetMember(memberName); var impl = (EventSymbol)b1.FindImplementationForInterfaceMember(member); Assert.False(impl.TypeWithAnnotations.Equals(member.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } var e3 = ia.GetMember("E3"); { var impl = (EventSymbol)b1.FindImplementationForInterfaceMember(e3); Assert.True(impl.TypeWithAnnotations.Equals(e3.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "IA", "B1" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var ev in type.GetMembers().OfType()) { Assert.True(ev.TypeWithAnnotations.Equals(ev.AddMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(ev.TypeWithAnnotations.Equals(ev.RemoveMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Overriding_17() { var source = @"#pragma warning disable 8618 class C { public static void Main() { } } abstract class A1 { public abstract string?[] P1 {get; set;} public abstract string[] P2 {get; set;} public abstract string?[] this[int x] {get; set;} public abstract string[] this[short x] {get; set;} } abstract class A2 { public abstract string?[]? P3 {get; set;} public abstract string?[]? this[long x] {get; set;} } class B1 : A1 { public override string[] P1 {get; set;} public override string[]? P2 {get; set;} public override string[] this[int x] // 1 { get {throw new System.NotImplementedException();} set {} } public override string[]? this[short x] // 2 { get {throw new System.NotImplementedException();} set {} } } class B2 : A2 { public override string?[]? P3 {get; set;} public override string?[]? this[long x] // 3 { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (27,39): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override string[] P1 {get; set;} Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(27, 39), // (28,35): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override string[]? P2 {get; set;} Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(28, 35), // (33,9): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // set {} Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(33, 9), // (38,9): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // get {throw new System.NotImplementedException();} Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(38, 9) ); foreach (var member in compilation.GetTypeByMetadataName("B1").GetMembers().OfType()) { Assert.False(member.TypeWithAnnotations.Equals(member.OverriddenProperty.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (var member in compilation.GetTypeByMetadataName("B2").GetMembers().OfType()) { Assert.True(member.TypeWithAnnotations.Equals(member.OverriddenProperty.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "A1", "B1", "A2", "B2" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var property in type.GetMembers().OfType()) { Assert.True(property.TypeWithAnnotations.Equals(property.GetMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(property.TypeWithAnnotations.Equals(property.SetMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Overriding_22() { var source = @"#pragma warning disable 8618 class C { public static void Main() { } } abstract class A1 { public abstract string?[] P1 {get; set;} // 1 public abstract string[] P2 {get; set;} public abstract string?[] this[int x] {get; set;} // 2 public abstract string[] this[short x] {get; set;} } class B1 : A1 { #nullable disable public override string[] P1 {get; set;} #nullable disable public override string[]? P2 {get; set;} // 3 #nullable disable public override string[] this[int x] { get {throw new System.NotImplementedException();} set {} } #nullable disable public override string[]? this[short x] // 4 { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }); compilation.VerifyDiagnostics( // (14,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract string?[] this[int x] {get; set;} // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 27), // (11,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract string?[] P1 {get; set;} // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 27), // (23,29): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override string[]? P2 {get; set;} // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 29), // (33,29): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override string[]? this[short x] // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(33, 29) ); } [Fact] public void Implementing_03() { var source = @"#pragma warning disable 8618 class C { public static void Main() { } } interface IA { string?[] P1 {get; set;} string[] P2 {get; set;} string?[] this[int x] {get; set;} string[] this[short x] {get; set;} } interface IA2 { string?[]? P3 {get; set;} string?[]? this[long x] {get; set;} } class B : IA, IA2 { public string[] P1 {get; set;} public string[]? P2 {get; set;} public string?[]? P3 {get; set;} public string[] this[int x] { get {throw new System.NotImplementedException();} set {} // 1 } public string[]? this[short x] { get {throw new System.NotImplementedException();} // 2 set {} } public string?[]? this[long x] { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (23,26): warning CS8613: Nullability of reference types in return type of 'string[]? B.P2.get' doesn't match implicitly implemented member 'string[] IA.P2.get'. // public string[]? P2 {get; set;} Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("string[]? B.P2.get", "string[] IA.P2.get").WithLocation(23, 26), // (29,9): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.this[int x].set' doesn't match implicitly implemented member 'void IA.this[int x].set'. // set {} // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void B.this[int x].set", "void IA.this[int x].set").WithLocation(29, 9), // (34,9): warning CS8613: Nullability of reference types in return type of 'string[]? B.this[short x].get' doesn't match implicitly implemented member 'string[] IA.this[short x].get'. // get {throw new System.NotImplementedException();} // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("string[]? B.this[short x].get", "string[] IA.this[short x].get").WithLocation(34, 9), // (22,30): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P1.set' doesn't match implicitly implemented member 'void IA.P1.set'. // public string[] P1 {get; set;} Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void B.P1.set", "void IA.P1.set").WithLocation(22, 30) ); var b = compilation.GetTypeByMetadataName("B"); foreach (var member in compilation.GetTypeByMetadataName("IA").GetMembers().OfType()) { var impl = (PropertySymbol)b.FindImplementationForInterfaceMember(member); Assert.False(impl.TypeWithAnnotations.Equals(member.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (var member in compilation.GetTypeByMetadataName("IA2").GetMembers().OfType()) { var impl = (PropertySymbol)b.FindImplementationForInterfaceMember(member); Assert.True(impl.TypeWithAnnotations.Equals(member.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "IA", "IA2", "B" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var property in type.GetMembers().OfType()) { Assert.True(property.TypeWithAnnotations.Equals(property.GetMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(property.TypeWithAnnotations.Equals(property.SetMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Implementing_04() { var source = @"#pragma warning disable 8618 class C { public static void Main() { } } interface IA { string?[] P1 {get; set;} string[] P2 {get; set;} string?[] this[int x] {get; set;} string[] this[short x] {get; set;} } interface IA2 { string?[]? P3 {get; set;} string?[]? this[long x] {get; set;} } class B : IA, IA2 { string[] IA.P1 {get; set;} string[]? IA.P2 {get; set;} string?[]? IA2.P3 {get; set;} string[] IA.this[int x] { get {throw new System.NotImplementedException();} set {} // 1 } string[]? IA.this[short x] { get {throw new System.NotImplementedException();} // 2 set {} } string?[]? IA2.this[long x] { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (22,26): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void IA.P1.set'. // string[] IA.P1 {get; set;} Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void IA.P1.set").WithLocation(22, 26), // (23,22): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'string[] IA.P2.get'. // string[]? IA.P2 {get; set;} Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("string[] IA.P2.get").WithLocation(23, 22), // (29,9): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void IA.this[int x].set'. // set {} // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void IA.this[int x].set").WithLocation(29, 9), // (34,9): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'string[] IA.this[short x].get'. // get {throw new System.NotImplementedException();} // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("string[] IA.this[short x].get").WithLocation(34, 9) ); var b = compilation.GetTypeByMetadataName("B"); foreach (var member in compilation.GetTypeByMetadataName("IA").GetMembers().OfType()) { var impl = (PropertySymbol)b.FindImplementationForInterfaceMember(member); Assert.False(impl.TypeWithAnnotations.Equals(member.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (var member in compilation.GetTypeByMetadataName("IA2").GetMembers().OfType()) { var impl = (PropertySymbol)b.FindImplementationForInterfaceMember(member); Assert.True(impl.TypeWithAnnotations.Equals(member.TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "IA", "IA2", "B" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var property in type.GetMembers().OfType()) { Assert.True(property.TypeWithAnnotations.Equals(property.GetMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(property.TypeWithAnnotations.Equals(property.SetMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Overriding_18() { var source = @" class C { public static void Main() { } } abstract class A { public abstract string[] M1(); public abstract T[] M2() where T : class; public abstract T?[]? M3() where T : class; } class B : A { public override string?[] M1() { return new string?[] {}; } public override S?[] M2() { return new S?[] {}; } public override S?[]? M3() { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (23,26): error CS0508: 'B.M2()': return type must be 'S[]' to match overridden member 'A.M2()' // public override S?[] M2() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M2").WithArguments("B.M2()", "A.M2()", "S[]").WithLocation(23, 26), // (28,27): error CS0508: 'B.M3()': return type must be 'S?[]' to match overridden member 'A.M3()' // public override S?[]? M3() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M3").WithArguments("B.M3()", "A.M3()", "S?[]").WithLocation(28, 27), // (18,31): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override string?[] M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(18, 31), // (23,26): error CS0453: The type 'S' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override S?[] M2() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M2").WithArguments("System.Nullable", "T", "S").WithLocation(23, 26), // (28,27): error CS0453: The type 'S' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override S?[]? M3() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M3").WithArguments("System.Nullable", "T", "S").WithLocation(28, 27)); var b = compilation.GetTypeByMetadataName("B"); foreach (string memberName in new[] { "M1", "M2", "M3" }) { var member = b.GetMember(memberName); Assert.False(member.ReturnTypeWithAnnotations.Equals(member.OverriddenMethod.ConstructIfGeneric(member.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))).ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } [Fact] [WorkItem(28684, "https://github.com/dotnet/roslyn/issues/28684")] public void Overriding_23() { var source = @" class C { public static void Main() { } } abstract class A { public abstract string[] M1(); public abstract T[] M2() where T : class; } class B : A { #nullable disable public override string?[] M1() { return new string?[] {}; } #nullable disable public override S?[] M2() { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (24,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override S?[] M2() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(24, 22), // (18,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override string?[] M1() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 27), // (24,26): error CS0508: 'B.M2()': return type must be 'S[]' to match overridden member 'A.M2()' // public override S?[] M2() Diagnostic(ErrorCode.ERR_CantChangeReturnTypeOnOverride, "M2").WithArguments("B.M2()", "A.M2()", "S[]").WithLocation(24, 26), // (18,31): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override string?[] M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(18, 31), // (24,26): error CS0453: The type 'S' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override S?[] M2() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M2").WithArguments("System.Nullable", "T", "S").WithLocation(24, 26), // (20,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new string?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(20, 26), // (26,21): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new S?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(26, 21) ); } [Fact] public void Implementing_05() { var source = @" class C { public static void Main() { } } interface IA { string[] M1(); T[] M2() where T : class; T?[]? M3() where T : class; } class B : IA { public string?[] M1() { return new string?[] {}; } public S?[] M2() where S : class { return new S?[] {}; } public S?[]? M3() where S : class { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (23,17): warning CS8613: Nullability of reference types in return type of 'S?[] B.M2()' doesn't match implicitly implemented member 'S[] IA.M2()'. // public S?[] M2() where S : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M2").WithArguments("S?[] B.M2()", "S[] IA.M2()").WithLocation(23, 17), // (18,22): warning CS8613: Nullability of reference types in return type of 'string?[] B.M1()' doesn't match implicitly implemented member 'string[] IA.M1()'. // public string?[] M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M1").WithArguments("string?[] B.M1()", "string[] IA.M1()").WithLocation(18, 22) ); var ia = compilation.GetTypeByMetadataName("IA"); var b = compilation.GetTypeByMetadataName("B"); foreach (var memberName in new[] { "M1", "M2" }) { var member = ia.GetMember(memberName); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.False(implementing.ReturnTypeWithAnnotations.Equals(implemented.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } { var member = ia.GetMember("M3"); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.True(implementing.ReturnTypeWithAnnotations.Equals(implemented.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } [Fact] public void Implementing_06() { var source = @" class C { public static void Main() { } } interface IA { string[] M1(); T[] M2() where T : class; T?[]? M3() where T : class; } class B : IA { string?[] IA.M1() { return new string?[] {}; } S?[] IA.M2() { return new S?[] {}; } S?[]? IA.M3() { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M2").WithArguments("B.M2()").WithLocation(23, 13), // (28,14): error CS0539: 'B.M3()' in explicit interface declaration is not found among members of the interface that can be implemented // S?[]? IA.M3() where S : class Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("B.M3()").WithLocation(28, 14), // (18,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'string[] IA.M1()'. // string?[] IA.M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M1").WithArguments("string[] IA.M1()").WithLocation(18, 18), // (16,11): error CS0535: 'B' does not implement interface member 'IA.M3()' // class B : IA Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IA").WithArguments("B", "IA.M3()").WithLocation(16, 11), // (16,11): error CS0535: 'B' does not implement interface member 'IA.M2()' // class B : IA Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IA").WithArguments("B", "IA.M2()").WithLocation(16, 11), // (23,13): error CS0453: The type 'S' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // S?[] IA.M2() where S : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M2").WithArguments("System.Nullable", "T", "S").WithLocation(23, 13), // (28,14): error CS0453: The type 'S' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // S?[]? IA.M3() where S : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M3").WithArguments("System.Nullable", "T", "S").WithLocation(28, 14), // (25,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // return new S?[] {}; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "S?").WithLocation(25, 20), // (30,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // return new S?[] {}; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "S?").WithLocation(30, 20) ); var ia = compilation.GetTypeByMetadataName("IA"); var b = compilation.GetTypeByMetadataName("B"); var member = ia.GetMember("M1"); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.False(implementing.ReturnTypeWithAnnotations.Equals(implemented.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); member = ia.GetMember("M2"); Assert.Null(b.FindImplementationForInterfaceMember(member)); member = ia.GetMember("M3"); Assert.Null(b.FindImplementationForInterfaceMember(member)); } [Fact] public void ImplementingNonNullWithNullable_01() { var source = @" interface IA { string[] M1(); T[] M2() where T : class; } class B : IA { #nullable disable string?[] IA.M1() { return new string?[] {}; } #nullable disable S?[] IA.M2() { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (17,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // S?[] IA.M2() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 6), // (17,13): error CS0539: 'B.M2()' in explicit interface declaration is not found among members of the interface that can be implemented // S?[] IA.M2() Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M2").WithArguments("B.M2()").WithLocation(17, 13), // (11,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string?[] IA.M1() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 11), // (11,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'string[] IA.M1()'. // string?[] IA.M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M1").WithArguments("string[] IA.M1()").WithLocation(11, 18), // (8,11): error CS0535: 'B' does not implement interface member 'IA.M2()' // class B : IA Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IA").WithArguments("B", "IA.M2()").WithLocation(8, 11), // (17,13): error CS0453: The type 'S' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // S?[] IA.M2() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M2").WithArguments("System.Nullable", "T", "S").WithLocation(17, 13), // (13,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new string?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 26), // (19,21): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new S?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 21), // (19,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // return new S?[] {}; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "S?").WithLocation(19, 20) ); } [Fact] [WorkItem(28684, "https://github.com/dotnet/roslyn/issues/28684")] public void ImplementingNonNullWithNullable_02() { var source = @" interface IA { string[] M1(); T[] M2() where T : class; } class B : IA { #nullable disable string?[] IA.M1() { return new string?[] {}; } #nullable disable S?[] IA.M2() where S : class { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (17,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // S?[] IA.M2() where S : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 6), // (17,13): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'S[] IA.M2()'. // S?[] IA.M2() where S : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M2").WithArguments("S[] IA.M2()").WithLocation(17, 13), // (11,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string?[] IA.M1() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 11), // (11,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'string[] IA.M1()'. // string?[] IA.M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M1").WithArguments("string[] IA.M1()").WithLocation(11, 18), // (13,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new string?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 26), // (19,21): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new S?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 21) ); } [Fact] public void ImplementingNullableWithNonNull_ReturnType() { var source = @" interface IA { #nullable disable string?[] M1(); #nullable disable T?[] M2() where T : class; } #nullable enable class B : IA { string[] IA.M1() => throw null!; S[] IA.M2() => throw null!; } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (7,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T?[] M2() where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 6), // (7,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T?[] M2() where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 5), // (5,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // string?[] M1(); Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 11) ); } [Fact] public void ImplementingNullableWithNonNull_Parameter() { var source = @" interface IA { #nullable disable void M1(string?[] x); #nullable disable void M2(T?[] x) where T : class; } #nullable enable class B : IA { void IA.M1(string[] x) => throw null!; void IA.M2(S[] x) => throw null!; } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (5,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void M1(string?[] x); Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 19), // (7,16): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void M2(T?[] x) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 16), // (7,17): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void M2(T?[] x) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 17), // (12,13): warning CS8617: Nullability of reference types in type of parameter 'x' doesn't match implemented member 'void IA.M1(string?[] x)'. // void IA.M1(string[] x) => throw null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M1").WithArguments("x", "void IA.M1(string?[] x)").WithLocation(12, 13), // (13,13): warning CS8617: Nullability of reference types in type of parameter 'x' doesn't match implemented member 'void IA.M2(S?[] x)'. // void IA.M2(S[] x) Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M2").WithArguments("x", "void IA.M2(S?[] x)").WithLocation(13, 13) ); } [Fact] public void ImplementingObliviousWithNonNull() { var source = @" interface IA { #nullable disable string[] M1(); #nullable disable T[] M2() where T : class; } #nullable enable class B : IA { string[] IA.M1() => throw null!; S[] IA.M2() => throw null!; } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); } [Fact] public void Overriding_19() { var source = @" class C { public static void Main() { } } abstract class A { public abstract void M1(string[] x); public abstract void M2(T[] x) where T : class; public abstract void M3(T?[]? x) where T : class; } class B : A { public override void M1(string?[] x) { } public override void M2(T?[] x) { } public override void M3(T?[]? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (22,26): error CS0115: 'B.M2(T?[])': no suitable method found to override // public override void M2(T?[] x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M2").WithArguments("B.M2(T?[])").WithLocation(22, 26), // (26,26): error CS0115: 'B.M3(T?[]?)': no suitable method found to override // public override void M3(T?[]? x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M3").WithArguments("B.M3(T?[]?)").WithLocation(26, 26), // (16,7): error CS0534: 'B' does not implement inherited abstract member 'A.M3(T?[]?)' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.M3(T?[]?)").WithLocation(16, 7), // (16,7): error CS0534: 'B' does not implement inherited abstract member 'A.M2(T[])' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.M2(T[])").WithLocation(16, 7), // (22,37): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M2(T?[] x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(22, 37), // (26,38): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M3(T?[]? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(26, 38) ); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.False(m1.Parameters[0].TypeWithAnnotations.Equals(m1.OverriddenMethod.ConstructIfGeneric(m1.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))).Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); var m2 = b.GetMember("M2"); Assert.Null(m2.OverriddenMethod); var m3 = b.GetMember("M3"); Assert.Null(m3.OverriddenMethod); } [Fact] [WorkItem(28684, "https://github.com/dotnet/roslyn/issues/28684")] public void Overriding_24() { var source = @" #nullable enable abstract class A { public abstract void M1(string[] x); public abstract void M2(T[] x) where T : class; } class B : A { #nullable disable public override void M1(string?[] x) { } #nullable disable public override void M2(T?[] x) { } } "; var compilation = CreateCompilation(new[] { source }); compilation.VerifyDiagnostics( // (18,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override void M2(T?[] x) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 33), // (13,35): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override void M1(string?[] x) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 35), // (18,26): error CS0115: 'B.M2(T?[])': no suitable method found to override // public override void M2(T?[] x) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "M2").WithArguments("B.M2(T?[])").WithLocation(18, 26), // (10,7): error CS0534: 'B' does not implement inherited abstract member 'A.M2(T[])' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.M2(T[])").WithLocation(10, 7), // (18,37): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void M2(T?[] x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(18, 37) ); } [Fact] public void Overriding_25() { var ilSource = @" .assembly extern mscorlib { .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } .assembly '<>' { } .module '<>.dll' .class public auto ansi beforefieldinit C`2 extends [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method C`2::.ctor } // end of class C`2 .class public abstract auto ansi beforefieldinit A extends [mscorlib]System.Object { .method public hidebysig newslot abstract virtual instance class C`2 M1() cil managed { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 01 00 00 ) } // end of method A::M1 .method family hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method A::.ctor } // end of class A .class public auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 86 6B 00 00 01 00 54 02 0D 41 6C 6C 6F 77 // ...k....T..Allow 4D 75 6C 74 69 70 6C 65 00 ) // Multiple. .method public hidebysig specialname rtspecialname instance void .ctor(uint8 transformFlag) cil managed { // Code size 9 (0x9) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret } // end of method NullableAttribute::.ctor .method public hidebysig specialname rtspecialname instance void .ctor(uint8[] transformFlags) cil managed { // Code size 9 (0x9) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret } // end of method NullableAttribute::.ctor } // end of class System.Runtime.CompilerServices.NullableAttribute "; var source = @" class C { public static void Main() { } } class B : A { public override C M1() { return new C(); } } "; var compilation = CreateCompilation(new[] { source }, new[] { CompileIL(ilSource, prependDefaultHeader: false) }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); var m1 = compilation.GetTypeByMetadataName("B").GetMember("M1"); Assert.Equal("C", m1.OverriddenMethod.ReturnTypeWithAnnotations.ToTestDisplayString()); Assert.Equal("C", m1.ReturnTypeWithAnnotations.ToTestDisplayString()); compilation.VerifyDiagnostics( // (11,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override C M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(11, 40) ); } [Fact] public void Overriding_26() { var source = @" class A { public virtual void M1(T? x) where T : class { } public virtual T? M2() where T : class { return null; } } class B : A { public override void M1(T? x) where T : class { } public override T? M2() where T : class { return null; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.False(m1.Parameters[0].Type.IsNullableType()); Assert.Equal(NullableAnnotation.Annotated, m1.Parameters[0].TypeWithAnnotations.NullableAnnotation); Assert.True(m1.Parameters[0].Type.IsReferenceType); Assert.False(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); var m2 = b.GetMember("M2"); Assert.False(m2.ReturnType.IsNullableType()); Assert.Equal(NullableAnnotation.Annotated, m2.ReturnTypeWithAnnotations.NullableAnnotation); Assert.True(m2.ReturnType.IsReferenceType); Assert.False(m2.OverriddenMethod.ReturnType.IsNullableType()); } [Fact] public void Overriding_27() { var source = @" class A { public virtual void M1(System.Nullable x) where T : struct { } public virtual void M2(T? x) where T : struct { } public virtual void M3(C x) where T : struct { } public virtual void M4(C> x) where T : struct { } public virtual void M5(C x) where T : class { } } class B : A { public override void M1(T? x) { } public override void M2(T? x) { } public override void M3(C x) { } public override void M4(C x) { } public override void M5(C x) where T : class { } } class C {} "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m3 = b.GetMember("M3"); var m4 = b.GetMember("M4"); var m5 = b.GetMember("M5"); Assert.True(((NamedTypeSymbol)m3.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m3.OverriddenMethod.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m4.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.True(((NamedTypeSymbol)m4.OverriddenMethod.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.False(((NamedTypeSymbol)m5.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); Assert.False(((NamedTypeSymbol)m5.OverriddenMethod.Parameters[0].Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].IsNullableType()); } [Fact] public void Overriding_28() { var source = @" class C { public static void Main() { } } abstract class A { public abstract string[] M1(); public abstract T[] M2() where T : class; public abstract T?[]? M3() where T : class; } class B : A { public override string?[] M1() { return new string?[] {}; } public override S?[] M2() where S : class { return new S?[] {}; } public override S?[]? M3() where S : class { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (23,26): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override S?[] M2() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M2").WithLocation(23, 26), // (18,31): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override string?[] M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(18, 31) ); var b = compilation.GetTypeByMetadataName("B"); foreach (string memberName in new[] { "M1", "M2" }) { var member = b.GetMember(memberName); Assert.False(member.ReturnTypeWithAnnotations.Equals(member.OverriddenMethod.ConstructIfGeneric(member.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))).ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } var m3 = b.GetMember("M3"); Assert.True(m3.ReturnTypeWithAnnotations.Equals(m3.OverriddenMethod.ConstructIfGeneric(m3.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))).ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } [Fact] [WorkItem(28684, "https://github.com/dotnet/roslyn/issues/28684")] public void Overriding_29() { var source = @" class C { public static void Main() { } } abstract class A { public abstract string[] M1(); public abstract T[] M2() where T : class; } class B : A { #nullable disable public override string?[] M1() { return new string?[] {}; } #nullable disable public override S?[] M2() where S : class { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (18,31): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override string?[] M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(18, 31), // (24,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override S?[] M2() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(24, 22), // (24,26): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override S?[] M2() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M2").WithLocation(24, 26), // (18,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override string?[] M1() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 27), // (20,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new string?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(20, 26), // (26,21): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // return new S?[] {}; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(26, 21) ); } [Fact] public void Overriding_30() { var source = @" class C { public static void Main() { } } abstract class A { public abstract void M1(string[] x); public abstract void M2(T[] x) where T : class; public abstract void M3(T?[]? x) where T : class; } class B : A { public override void M1(string?[] x) { } public override void M2(T?[] x) where T : class { } public override void M3(T?[]? x) where T : class { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( ); var b = compilation.GetTypeByMetadataName("B"); foreach (string memberName in new[] { "M1", "M2" }) { var member = b.GetMember(memberName); Assert.False(member.Parameters[0].TypeWithAnnotations.Equals(member.OverriddenMethod.ConstructIfGeneric(member.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))).Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } var m3 = b.GetMember("M3"); Assert.True(m3.Parameters[0].TypeWithAnnotations.Equals(m3.OverriddenMethod.ConstructIfGeneric(m3.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))).Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } [Fact] [WorkItem(28684, "https://github.com/dotnet/roslyn/issues/28684")] public void Overriding_31() { var source = @" #nullable enable abstract class A { public abstract void M1(string[] x); public abstract void M2(T[] x) where T : class; } class B : A { #nullable disable public override void M1(string?[] x) { } #nullable disable public override void M2(T?[] x) where T : class { } } "; var compilation = CreateCompilation(new[] { source }); compilation.VerifyDiagnostics( // (18,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override void M2(T?[] x) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 33), // (13,35): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public override void M1(string?[] x) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 35) ); } [Fact] [WorkItem(29847, "https://github.com/dotnet/roslyn/issues/29847")] public void Overriding_32() { var source = @" class A { public virtual void M1(T? x) where T : struct { } public virtual void M1(T? x) where T : class { } } class B : A { public override void M1(T? x) where T : class { } } class C { public virtual void M2(T? x) where T : class { } public virtual void M2(T? x) where T : struct { } } class D : C { public override void M2(T? x) where T : class { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.False(m1.Parameters[0].Type.IsNullableType()); Assert.False(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); var d = compilation.GetTypeByMetadataName("D"); var m2 = d.GetMember("M2"); Assert.False(m2.Parameters[0].Type.IsNullableType()); Assert.False(m2.OverriddenMethod.Parameters[0].Type.IsNullableType()); } [Fact] [WorkItem(29847, "https://github.com/dotnet/roslyn/issues/29847")] public void Overriding_33() { var source = @" class A { public virtual void M1(T? x) where T : struct { } public virtual void M1(T? x) where T : class { } } class B : A { public override void M1(T? x) where T : struct { } } class C { public virtual void M2(T? x) where T : class { } public virtual void M2(T? x) where T : struct { } } class D : C { public override void M2(T? x) where T : struct { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var b = compilation.GetTypeByMetadataName("B"); var m1 = b.GetMember("M1"); Assert.True(m1.Parameters[0].Type.IsNullableType()); Assert.True(m1.OverriddenMethod.Parameters[0].Type.IsNullableType()); var d = compilation.GetTypeByMetadataName("D"); var m2 = d.GetMember("M2"); Assert.True(m2.Parameters[0].Type.IsNullableType()); Assert.True(m2.OverriddenMethod.Parameters[0].Type.IsNullableType()); } [Fact] [WorkItem(33276, "https://github.com/dotnet/roslyn/issues/33276")] public void Overriding_34() { var source1 = @" public class MyEntity { } public abstract class BaseController where T : MyEntity { public abstract void SomeMethod(R? lite) where R : MyEntity; } "; var source2 = @" class DerivedController : BaseController where T : MyEntity { Table table = null!; public override void SomeMethod(R? lite) where R : class { table.OtherMethod(lite); } } class Table where T : MyEntity { public void OtherMethod(R? lite) where R : MyEntity { lite?.ToString(); } } "; var compilation1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { reference }); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2); } } [Fact] [WorkItem(31676, "https://github.com/dotnet/roslyn/issues/31676")] public void Overriding_35() { var source1 = @" using System; namespace Microsoft.EntityFrameworkCore.TestUtilities { public abstract class QueryAsserterBase { public abstract void AssertQueryScalar( Func, IQueryable>> actualQuery) where TResult : struct; } } public interface IQueryable { } "; var source2 = @" using System; namespace Microsoft.EntityFrameworkCore.TestUtilities { public class QueryAsserter : QueryAsserterBase { public override void AssertQueryScalar( Func, IQueryable> actualQuery) { } } } "; foreach (var options1 in new[] { WithNonNullTypesTrue(), WithNonNullTypesFalse() }) { var compilation1 = CreateCompilation(new[] { source1 }, options: options1); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { foreach (var options2 in new[] { WithNonNullTypesTrue(), WithNonNullTypesFalse() }) { var compilation2 = CreateCompilation(new[] { source2 }, options: options2, references: new[] { reference }); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2); } } var compilation3 = CreateCompilation(new[] { source1, source2 }, options: options1); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3); var compilation4 = CreateCompilation(new[] { source2, source1 }, options: options1); compilation4.VerifyDiagnostics(); CompileAndVerify(compilation4); } } [Fact] public void Override_NullabilityCovariance_01() { var src = @" using System; interface I {} class A { public virtual object? M() => null; public virtual (object?, object?) M2() => throw null!; public virtual I M3() => throw null!; public virtual ref object? M4() => throw null!; public virtual ref readonly object? M5() => throw null!; public virtual Func? P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; public virtual object? P3 => null!; public virtual event Func? E1 { add {} remove {} } public virtual event Func E2 { add {} remove {} } } class B : A { public override object M() => null!; public override (object, object) M2() => throw null!; public override I M3() => throw null!; public override ref object M4() => throw null!; // warn public override ref readonly object M5() => throw null!; public override Func P1 { get; set; } = null!; // warn public override Func P2 { get; set; } = null!; // warn public override object P3 => null!; // ok public override event Func E1 { add {} remove {} } // warn public override event Func E2 { add {} remove {} } // warn } class C : B { public override object? M() => null; // warn public override (object?, object?) M2() => throw null!; // warn public override I M3() => throw null!; // warn public override ref object? M4() => throw null!; // warn public override ref readonly object? M5() => throw null!; // warn public override Func? P1 { get; set; } = null!; // warn public override Func P2 { get; set; } = null!; // warn public override object? P3 => null!; // warn public override event Func? E1 { add {} remove {} } // ok public override event Func E2 { add {} remove {} } // ok } class D : C { public override object M() => null!; public override (object, object) M2() => throw null!; public override I M3() => throw null!; public override ref object M4() => throw null!; // warn public override ref readonly object M5() => throw null!; public override Func P1 { get; set; } = null!; // warn public override Func P2 { get; set; } = null!; // warn public override object P3 => null!; // ok public override event Func E1 { add {} remove {} } // ok public override event Func E2 { add {} remove {} } // ok } class E : D { public override object? M() => null; // warn public override (object?, object?) M2() => throw null!; // warn public override I M3() => throw null!; // warn public override ref object? M4() => throw null!; // warn public override ref readonly object? M5() => throw null!; // warn public override Func? P1 { get; set; } = null!; // warn public override Func P2 { get; set; } = null!; // warn public override object? P3 => null!; // warn public override event Func? E1 { add {} remove {} } // warn public override event Func E2 { add {} remove {} } // warn }"; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,32): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override ref object M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M4").WithLocation(23, 32), // (25,44): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override Func P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(25, 44), // (26,44): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override Func P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(26, 44), // (28,40): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event Func E1 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E1").WithLocation(28, 40), // (29,40): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event Func E2 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E2").WithLocation(29, 40), // (33,29): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? M() => null; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M").WithLocation(33, 29), // (34,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override (object?, object?) M2() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M2").WithLocation(34, 40), // (35,32): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override I M3() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M3").WithLocation(35, 32), // (36,33): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override ref object? M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M4").WithLocation(36, 33), // (37,42): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override ref readonly object? M5() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M5").WithLocation(37, 42), // (38,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override Func? P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(38, 40), // (39,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override Func P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(39, 40), // (40,35): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? P3 => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "null!").WithLocation(40, 35), // (49,32): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override ref object M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M4").WithLocation(49, 32), // (51,44): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override Func P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(51, 44), // (52,44): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override Func P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(52, 44), // (54,40): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event Func E1 { add {} remove {} } // ok Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E1").WithLocation(54, 40), // (55,40): warning CS8608: Nullability of reference types in type doesn't match overridden member. // public override event Func E2 { add {} remove {} } // ok Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride, "E2").WithLocation(55, 40), // (59,29): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? M() => null; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M").WithLocation(59, 29), // (60,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override (object?, object?) M2() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M2").WithLocation(60, 40), // (61,32): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override I M3() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M3").WithLocation(61, 32), // (62,33): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override ref object? M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M4").WithLocation(62, 33), // (63,42): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override ref readonly object? M5() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M5").WithLocation(63, 42), // (64,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override Func? P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(64, 40), // (65,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override Func P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(65, 40), // (66,35): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? P3 => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "null!").WithLocation(66, 35) ); } [Fact] public void Override_NullabilityCovariance_02() { var src = @" using System; class A { public virtual Func? P1 { get; set; } = null!; } class B : A { public override Func P1 { get => null!; } } class C : B { public override Func P1 { get; set; } = null!; // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,44): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override Func P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(14, 44) ); } [Fact] public void Override_NullabilityCovariance_03() { var src = @" using System; class B { public virtual Func P1 { get; set; } = null!; } class C : B { public override Func? P1 { set {} } } class D : C { public override Func? P1 { get; set; } = null!; // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,40): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override Func? P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(14, 40) ); } [Fact] public void Override_NullabilityContravariance_01() { var src = @" interface I {} class A { public virtual void M(object o) { } public virtual void M2((object, object) t) { } public virtual void M3(I i) { } public virtual void M4(ref object o) { } public virtual void M5(out object o) => throw null!; public virtual void M6(in object o) { } public virtual object this[object o] { get => null!; set { } } public virtual string this[string s] => null!; public virtual string this[int[] a] { set { } } } class B : A { public override void M(object? o) { } public override void M2((object?, object?) t) { } public override void M3(I i) { } public override void M4(ref object? o) { } // warn public override void M5(out object? o) => throw null!; // warn public override void M6(in object? o) { } public override object? this[object? o] { get => null!; set { } } public override string this[string? s] => null!; public override string this[int[]? a] { set { } } } class C : B { public override void M(object o) { } // warn public override void M2((object, object) t) { } // warn public override void M3(I i) { } // warn public override void M4(ref object o) { } // warn public override void M5(out object o) => throw null!; public override void M6(in object o) { } // warn public override object this[object o] { get => null!; set { } } public override string this[string s] => null!; public override string this[int[] a] { set { } } } class D : C { public override void M(object? o) { } public override void M2((object?, object?) t) { } public override void M3(I i) { } public override void M4(ref object? o) { } // warn public override void M5(out object? o) => throw null!; // warn public override void M6(in object? o) { } public override object? this[object? o] { get => null!; set { } } public override string this[string? s] => null!; public override string this[int[]? a] { set { } } } class E : D { public override void M(object o) { } // warn public override void M2((object, object) t) { } // warn public override void M3(I i) { } // warn public override void M4(ref object o) { } // warn public override void M5(out object o) => throw null!; public override void M6(in object o) { } // warn public override object this[object o] { get => null!; set { } } public override string this[string s] => null!; public override string this[int[] a] { set { } } }"; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M4(ref object? o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M4").WithArguments("o").WithLocation(20, 26), // (21,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M5(out object? o) => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M5").WithArguments("o").WithLocation(21, 26), // (23,47): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? this[object? o] { get => null!; set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(23, 47), // (29,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M(object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M").WithArguments("o").WithLocation(29, 26), // (30,26): warning CS8610: Nullability of reference types in type of parameter 't' doesn't match overridden member. // public override void M2((object, object) t) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M2").WithArguments("t").WithLocation(30, 26), // (31,26): warning CS8610: Nullability of reference types in type of parameter 'i' doesn't match overridden member. // public override void M3(I i) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M3").WithArguments("i").WithLocation(31, 26), // (32,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M4(ref object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M4").WithArguments("o").WithLocation(32, 26), // (34,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M6(in object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M6").WithArguments("o").WithLocation(34, 26), // (35,59): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override object this[object o] { get => null!; set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("o").WithLocation(35, 59), // (35,59): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override object this[object o] { get => null!; set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(35, 59), // (36,46): warning CS8610: Nullability of reference types in type of parameter 's' doesn't match overridden member. // public override string this[string s] => null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "null!").WithArguments("s").WithLocation(36, 46), // (37,44): warning CS8610: Nullability of reference types in type of parameter 'a' doesn't match overridden member. // public override string this[int[] a] { set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("a").WithLocation(37, 44), // (44,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M4(ref object? o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M4").WithArguments("o").WithLocation(44, 26), // (45,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M5(out object? o) => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M5").WithArguments("o").WithLocation(45, 26), // (47,47): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? this[object? o] { get => null!; set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "get").WithLocation(47, 47), // (53,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M(object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M").WithArguments("o").WithLocation(53, 26), // (54,26): warning CS8610: Nullability of reference types in type of parameter 't' doesn't match overridden member. // public override void M2((object, object) t) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M2").WithArguments("t").WithLocation(54, 26), // (55,26): warning CS8610: Nullability of reference types in type of parameter 'i' doesn't match overridden member. // public override void M3(I i) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M3").WithArguments("i").WithLocation(55, 26), // (56,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M4(ref object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M4").WithArguments("o").WithLocation(56, 26), // (58,26): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override void M6(in object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M6").WithArguments("o").WithLocation(58, 26), // (59,59): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override object this[object o] { get => null!; set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("o").WithLocation(59, 59), // (59,59): warning CS8610: Nullability of reference types in type of parameter 'value' doesn't match overridden member. // public override object this[object o] { get => null!; set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("value").WithLocation(59, 59), // (60,46): warning CS8610: Nullability of reference types in type of parameter 's' doesn't match overridden member. // public override string this[string s] => null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "null!").WithArguments("s").WithLocation(60, 46), // (61,44): warning CS8610: Nullability of reference types in type of parameter 'a' doesn't match overridden member. // public override string this[int[] a] { set { } } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("a").WithLocation(61, 44) ); } [Fact] public void Override_NullabilityContravariance_02() { var src = @" class B { public virtual object? this[object? o] { get => null!; set { } } } class C : B { #nullable disable public override object this[object o] { set { } } #nullable enable } class D : C { public override object this[object? o] { get => null!; } } class E : D { public override object this[object o] { get => null!; set { } } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,45): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override object this[object o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "get").WithArguments("o").WithLocation(18, 45) ); } [Fact] public void Override_NullabilityContravariance_03() { var src = @" class B { public virtual object? this[object? o] { get => null!; set { } } } class C : B { public override object this[object? o] { get => null!; } } class D : C { #nullable disable public override object this[object o] { set { } } #nullable enable } class E : D { public override object this[object o] { get => null!; set { } } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,45): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override object this[object o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "get").WithArguments("o").WithLocation(18, 45) ); } [Fact] public void OverrideConstraintVariance() { var src = @" using System.Collections.Generic; class A { public virtual List? M(List? t) => null!; } class B : A { public override List M(List t) => null!; } class C : B { public override List? M(List? t) => null!; } class D : C { public override List M(List t) => null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,29): warning CS8610: Nullability of reference types in type of parameter 't' doesn't match overridden member. // public override List M(List t) => null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M").WithArguments("t").WithLocation(9, 29), // (13,30): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override List? M(List? t) => null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M").WithLocation(13, 30), // (17,29): warning CS8610: Nullability of reference types in type of parameter 't' doesn't match overridden member. // public override List M(List t) => null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M").WithArguments("t").WithLocation(17, 29)); } [Fact] public void OverrideVarianceGenericBase() { var comp = CreateCompilation(@" class A { public virtual T M(T t) => default!; } #nullable enable class B : A { public override object? M(object? o) => null!; // warn } class C : A { public override object M(object o) => null!; // warn } #nullable disable class D : A { #nullable enable public override object? M(object? o) => null!; } class E : A { #nullable disable public override object M(object o) => null!; } #nullable enable class F : A { #nullable disable public override object M(object o) => null; } "); comp.VerifyDiagnostics( // (9,29): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override object? M(object? o) => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M").WithLocation(9, 29), // (13,28): warning CS8610: Nullability of reference types in type of parameter 'o' doesn't match overridden member. // public override object M(object o) => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M").WithArguments("o").WithLocation(13, 28)); } [Fact] public void NullableVarianceConsumer() { var comp = CreateCompilation(@" class A { public virtual object? M() => null; } class B : A { public override object M() => null; // warn } class C { void M() { var b = new B(); b.M().ToString(); A a = b; a.M().ToString(); // warn } }", options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,35): warning CS8603: Possible null reference return. // public override object M() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(8, 35), // (17,9): warning CS8602: Dereference of a possibly null reference. // a.M().ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.M()").WithLocation(17, 9)); } [Fact] public void Implement_NullabilityCovariance_Implicit_01() { var src = @" using System; interface I {} interface A { object? M(); (object?, object?) M2(); I M3(); ref object? M4(); ref readonly object? M5(); Func? P1 { get; set; } Func P2 { get; set; } object? P3 {get;} event Func? E1; event Func E2; } class B : A { public object M() => null!; public (object, object) M2() => throw null!; public I M3() => throw null!; public ref object M4() => throw null!; // warn public ref readonly object M5() => throw null!; public Func P1 { get; set; } = null!; // warn public Func P2 { get; set; } = null!; // warn public object P3 => null!; // ok public event Func E1 { add {} remove {} } // warn public event Func E2 { add {} remove {} } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,23): warning CS8613: Nullability of reference types in return type of 'ref object B.M4()' doesn't match implicitly implemented member 'ref object? A.M4()'. // public ref object M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M4").WithArguments("ref object B.M4()", "ref object? A.M4()").WithLocation(23, 23), // (25,35): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P1.set' doesn't match implicitly implemented member 'void A.P1.set'. // public Func P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void B.P1.set", "void A.P1.set").WithLocation(25, 35), // (26,35): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P2.set' doesn't match implicitly implemented member 'void A.P2.set'. // public Func P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void B.P2.set", "void A.P2.set").WithLocation(26, 35), // (28,31): warning CS8612: Nullability of reference types in type of 'event Func B.E1' doesn't match implicitly implemented member 'event Func? A.E1'. // public event Func E1 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "E1").WithArguments("event Func B.E1", "event Func? A.E1").WithLocation(28, 31), // (29,31): warning CS8612: Nullability of reference types in type of 'event Func B.E2' doesn't match implicitly implemented member 'event Func A.E2'. // public event Func E2 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "E2").WithArguments("event Func B.E2", "event Func A.E2").WithLocation(29, 31) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_02() { var src = @" using System; interface I {} interface B { object M(); (object, object) M2(); I M3(); ref object M4(); ref readonly object M5(); Func P1 { get; set; } Func P2 { get; set; } object P3 { get; } event Func E1; event Func E2; } class C : B { public object? M() => null; // warn public (object?, object?) M2() => throw null!; // warn public I M3() => throw null!; // warn public ref object? M4() => throw null!; // warn public ref readonly object? M5() => throw null!; // warn public Func? P1 { get; set; } = null!; // warn public Func P2 { get; set; } = null!; // warn public object? P3 => null!; // warn public event Func? E1 { add {} remove {} } // ok public event Func E2 { add {} remove {} } // ok } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,20): warning CS8613: Nullability of reference types in return type of 'object? C.M()' doesn't match implicitly implemented member 'object B.M()'. // public object? M() => null; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M").WithArguments("object? C.M()", "object B.M()").WithLocation(20, 20), // (21,31): warning CS8613: Nullability of reference types in return type of '(object?, object?) C.M2()' doesn't match implicitly implemented member '(object, object) B.M2()'. // public (object?, object?) M2() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M2").WithArguments("(object?, object?) C.M2()", "(object, object) B.M2()").WithLocation(21, 31), // (22,23): warning CS8613: Nullability of reference types in return type of 'I C.M3()' doesn't match implicitly implemented member 'I B.M3()'. // public I M3() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M3").WithArguments("I C.M3()", "I B.M3()").WithLocation(22, 23), // (23,24): warning CS8613: Nullability of reference types in return type of 'ref object? C.M4()' doesn't match implicitly implemented member 'ref object B.M4()'. // public ref object? M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M4").WithArguments("ref object? C.M4()", "ref object B.M4()").WithLocation(23, 24), // (24,33): warning CS8613: Nullability of reference types in return type of 'ref readonly object? C.M5()' doesn't match implicitly implemented member 'ref readonly object B.M5()'. // public ref readonly object? M5() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M5").WithArguments("ref readonly object? C.M5()", "ref readonly object B.M5()").WithLocation(24, 33), // (25,31): warning CS8613: Nullability of reference types in return type of 'Func? C.P1.get' doesn't match implicitly implemented member 'Func B.P1.get'. // public Func? P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("Func? C.P1.get", "Func B.P1.get").WithLocation(25, 31), // (26,31): warning CS8613: Nullability of reference types in return type of 'Func C.P2.get' doesn't match implicitly implemented member 'Func B.P2.get'. // public Func P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("Func C.P2.get", "Func B.P2.get").WithLocation(26, 31), // (27,26): warning CS8613: Nullability of reference types in return type of 'object? C.P3.get' doesn't match implicitly implemented member 'object B.P3.get'. // public object? P3 => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "null!").WithArguments("object? C.P3.get", "object B.P3.get").WithLocation(27, 26) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_05() { var src = @" using System; interface I {} interface A { object? M(); (object?, object?) M2(); I M3(); ref object? M4(); ref readonly object? M5(); Func? P1 { get; set; } Func P2 { get; set; } object? P3 {get;} event Func? E1; event Func E2; } class B { public object M() => null!; public (object, object) M2() => throw null!; public I M3() => throw null!; public ref object M4() => throw null!; // warn public ref readonly object M5() => throw null!; public Func P1 { get; set; } = null!; // warn public Func P2 { get; set; } = null!; // warn public object P3 => null!; // ok public event Func E1 { add {} remove {} } // warn public event Func E2 { add {} remove {} } // warn } class C : B, A {} "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (31,14): warning CS8613: Nullability of reference types in return type of 'ref object B.M4()' doesn't match implicitly implemented member 'ref object? A.M4()'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "A").WithArguments("ref object B.M4()", "ref object? A.M4()").WithLocation(31, 14), // (31,14): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P1.set' doesn't match implicitly implemented member 'void A.P1.set'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "A").WithArguments("value", "void B.P1.set", "void A.P1.set").WithLocation(31, 14), // (31,14): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P2.set' doesn't match implicitly implemented member 'void A.P2.set'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "A").WithArguments("value", "void B.P2.set", "void A.P2.set").WithLocation(31, 14), // (31,14): warning CS8612: Nullability of reference types in type of 'event Func B.E1' doesn't match implicitly implemented member 'event Func? A.E1'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "A").WithArguments("event Func B.E1", "event Func? A.E1").WithLocation(31, 14), // (31,14): warning CS8612: Nullability of reference types in type of 'event Func B.E2' doesn't match implicitly implemented member 'event Func A.E2'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation, "A").WithArguments("event Func B.E2", "event Func A.E2").WithLocation(31, 14) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_06() { var src = @" using System; interface A { Func? P1 { get; set; } Func P2 { get; set; } } class B { public virtual Func P1 { get; set; } = null!; // warn public virtual Func P2 { get; set; } = null!; // warn } class C : B, A { public override Func P1 { get => null!;} public override Func P2 => null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,14): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P2.set' doesn't match implicitly implemented member 'void A.P2.set'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "A").WithArguments("value", "void B.P2.set", "void A.P2.set").WithLocation(14, 14), // (14,14): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void B.P1.set' doesn't match implicitly implemented member 'void A.P1.set'. // class C : B, A Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "A").WithArguments("value", "void B.P1.set", "void A.P1.set").WithLocation(14, 14) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_07() { var src = @" using System; interface A { Func? P1 { get; set; } Func P2 { get; set; } } class B { public virtual Func? P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; } class C : B, A { public override Func P1 { get => null!;} public override Func P2 => null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_08() { var src = @" using System; interface A { Func? P1 { get; set; } Func P2 { get; set; } } class B { public virtual Func? P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; } #pragma warning disable CS8610 class C : B, A { public override Func P1 { set {} } // warn public override Func P2 { set; } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,39): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void C.P1.set' doesn't match implicitly implemented member 'void A.P1.set'. // public override Func P1 { set {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void C.P1.set", "void A.P1.set").WithLocation(16, 39), // (17,39): error CS8051: Auto-implemented properties must have get accessors. // public override Func P2 { set; } // warn Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, "set").WithArguments("C.P2.set").WithLocation(17, 39), // (17,39): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void C.P2.set' doesn't match implicitly implemented member 'void A.P2.set'. // public override Func P2 { set; } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void C.P2.set", "void A.P2.set").WithLocation(17, 39) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_09() { var src = @" using System; interface A { Func? P1 { get; set; } Func P2 { get; set; } } class B { public virtual Func P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; } class C : B, A { public override Func? P1 { set {} } public override Func P2 { set {} } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_10() { var src = @" using System; interface A { Func? P1 { get => null!; private set {} } Func P2 { get => null!; private set {} } } class B : A { public Func P1 { get; set; } = null!; public Func P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_11() { var src = @" using System; interface A { Func? P1 { get => null!; private set {} } Func P2 { get => null!; private set {} } } class B : A { public Func P1 { get; } = null!; public Func P2 { get; } = null!; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_12() { var src = @" using System; interface A { Func? P1 { get; } Func P2 { get; } } class B : A { public Func P1 { get; set; } = null!; public Func P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_13() { var src = @" using System; interface A { Func? P1 { get; set; } Func P2 { get; set; } } class B : A { public Func P1 { get; } = null!; public Func P2 { get; } = null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): error CS0535: 'B' does not implement interface member 'A.P2.set' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.P2.set").WithLocation(9, 11), // (9,11): error CS0535: 'B' does not implement interface member 'A.P1.set' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.P1.set").WithLocation(9, 11) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_14() { var src = @" using System; interface B { Func P1 { get; set; } Func P2 { get; set; } } class C { public virtual Func? P1 { get; set; } = null!; // warn public virtual Func P2 { get; set; } = null!; // warn } class D : C, B { public override Func? P1 { set {} } public override Func P2 { set {} } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,14): warning CS8613: Nullability of reference types in return type of 'Func C.P2.get' doesn't match implicitly implemented member 'Func B.P2.get'. // class D : C, B Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "B").WithArguments("Func C.P2.get", "Func B.P2.get").WithLocation(14, 14), // (14,14): warning CS8613: Nullability of reference types in return type of 'Func? C.P1.get' doesn't match implicitly implemented member 'Func B.P1.get'. // class D : C, B Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "B").WithArguments("Func? C.P1.get", "Func B.P1.get").WithLocation(14, 14) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_15() { var src = @" using System; interface B { Func P1 { get; set; } Func P2 { get; set; } } class C { public virtual Func P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; } class D : C, B { public override Func? P1 { set {} } public override Func P2 { set {} } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_16() { var src = @" using System; interface B { Func P1 { get; set; } Func P2 { get; set; } } class C { public virtual Func P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; } #pragma warning disable CS8609 class D : C, B { public override Func? P1 { get; } = null!; // warn public override Func P2 { get => null!; } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,35): error CS8080: Auto-implemented properties must override all accessors of the overridden property. // public override Func? P1 { get; } = null!; // warn Diagnostic(ErrorCode.ERR_AutoPropertyMustOverrideSet, "P1").WithArguments("D.P1").WithLocation(17, 35), // (17,40): warning CS8613: Nullability of reference types in return type of 'Func? D.P1.get' doesn't match implicitly implemented member 'Func B.P1.get'. // public override Func? P1 { get; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("Func? D.P1.get", "Func B.P1.get").WithLocation(17, 40), // (18,40): warning CS8613: Nullability of reference types in return type of 'Func D.P2.get' doesn't match implicitly implemented member 'Func B.P2.get'. // public override Func P2 { get => null!; } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("Func D.P2.get", "Func B.P2.get").WithLocation(18, 40) ); } [Fact] public void Implement_NullabilityCovariance_Implicit_17() { var src = @" using System; interface B { Func P1 { get; set; } Func P2 { get; set; } } class C { public virtual Func? P1 { get; set; } = null!; public virtual Func P2 { get; set; } = null!; } class D : C, B { public override Func P1 { get => null!; } public override Func P2 { get => null!; } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_18() { var src = @" using System; interface B { Func P1 { private get => null!; set{} } Func P2 { private get => null!; set{} } } class C : B { public Func? P1 { get; set; } = null!; public Func P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_19() { var src = @" using System; interface B { Func P1 { private get => null!; set{} } Func P2 { private get => null!; set{} } } class C : B { public Func? P1 { set{} } public Func P2 { set{} } } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_20() { var src = @" using System; interface B { Func P1 { set; } Func P2 { set; } } class C : B { public Func? P1 { get; set; } public Func P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Implicit_21() { var src = @" using System; interface B { Func P1 { get; set; } Func P2 { get; set; } } class C : B { public Func? P1 { set {} } public Func P2 { set {} } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): error CS0535: 'C' does not implement interface member 'B.P1.get' // class C : B Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "B").WithArguments("C", "B.P1.get").WithLocation(9, 11), // (9,11): error CS0535: 'C' does not implement interface member 'B.P2.get' // class C : B Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "B").WithArguments("C", "B.P2.get").WithLocation(9, 11) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_01() { var src = @" using System; interface I {} interface A { object? M(); (object?, object?) M2(); I M3(); ref object? M4(); ref readonly object? M5(); Func? P1 { get; set; } Func P2 { get; set; } object? P3 {get;} event Func? E1; event Func E2; } class B : A { object A.M() => null!; (object, object) A.M2() => throw null!; I A.M3() => throw null!; ref object A.M4() => throw null!; // warn ref readonly object A.M5() => throw null!; Func A.P1 { get; set; } = null!; // warn Func A.P2 { get; set; } = null!; // warn object A.P3 => null!; // ok event Func A.E1 { add {} remove {} } // warn event Func A.E2 { add {} remove {} } // warn } class C : B, A {} "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'ref object? A.M4()'. // ref object A.M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M4").WithArguments("ref object? A.M4()").WithLocation(23, 18), // (25,30): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void A.P1.set'. // Func A.P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void A.P1.set").WithLocation(25, 30), // (26,30): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void A.P2.set'. // Func A.P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void A.P2.set").WithLocation(26, 30), // (28,26): warning CS8615: Nullability of reference types in type doesn't match implemented member 'event Func? A.E1'. // event Func A.E1 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation, "E1").WithArguments("event Func? A.E1").WithLocation(28, 26), // (29,26): warning CS8615: Nullability of reference types in type doesn't match implemented member 'event Func A.E2'. // event Func A.E2 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation, "E2").WithArguments("event Func A.E2").WithLocation(29, 26) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_02() { var src = @" using System; interface I {} interface B { object M(); (object, object) M2(); I M3(); ref object M4(); ref readonly object M5(); Func P1 { get; set; } Func P2 { get; set; } object P3 { get; } event Func E1; event Func E2; } class C : B { object? B.M() => null; // warn (object?, object?) B.M2() => throw null!; // warn I B.M3() => throw null!; // warn ref object? B.M4() => throw null!; // warn ref readonly object? B.M5() => throw null!; // warn Func? B.P1 { get; set; } = null!; // warn Func B.P2 { get; set; } = null!; // warn object? B.P3 => null!; // warn event Func? B.E1 { add {} remove {} } // ok event Func B.E2 { add {} remove {} } // ok } class D : C, B {} "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,15): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'object B.M()'. // object? B.M() => null; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M").WithArguments("object B.M()").WithLocation(20, 15), // (21,26): warning CS8616: Nullability of reference types in return type doesn't match implemented member '(object, object) B.M2()'. // (object?, object?) B.M2() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M2").WithArguments("(object, object) B.M2()").WithLocation(21, 26), // (22,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'I B.M3()'. // I B.M3() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M3").WithArguments("I B.M3()").WithLocation(22, 18), // (23,19): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'ref object B.M4()'. // ref object? B.M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M4").WithArguments("ref object B.M4()").WithLocation(23, 19), // (24,28): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'ref readonly object B.M5()'. // ref readonly object? B.M5() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M5").WithArguments("ref readonly object B.M5()").WithLocation(24, 28), // (25,26): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'Func B.P1.get'. // Func? B.P1 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("Func B.P1.get").WithLocation(25, 26), // (26,26): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'Func B.P2.get'. // Func B.P2 { get; set; } = null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("Func B.P2.get").WithLocation(26, 26), // (27,21): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'object B.P3.get'. // object? B.P3 => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "null!").WithArguments("object B.P3.get").WithLocation(27, 21) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_03() { var src = @" using System; interface I {} interface A { object? M(); (object?, object?) M2(); I M3(); ref object? M4(); ref readonly object? M5(); Func? P1 { get; set; } Func P2 { get; set; } object? P3 {get;} event Func? E1; event Func E2; } interface B : A { object A.M() => null!; (object, object) A.M2() => throw null!; I A.M3() => throw null!; ref object A.M4() => throw null!; // warn ref readonly object A.M5() => throw null!; Func A.P1 { get => null!; set {} } // warn Func A.P2 { get => null!; set {} } // warn object A.P3 => null!; // ok event Func A.E1 { add {} remove {} } // warn event Func A.E2 { add {} remove {} } // warn } class C : B, A {} interface D : B, A {} "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'ref object? A.M4()'. // ref object A.M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M4").WithArguments("ref object? A.M4()").WithLocation(23, 18), // (25,39): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void A.P1.set'. // Func A.P1 { get => null!; set {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void A.P1.set").WithLocation(25, 39), // (26,39): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void A.P2.set'. // Func A.P2 { get => null!; set {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void A.P2.set").WithLocation(26, 39), // (28,26): warning CS8615: Nullability of reference types in type doesn't match implemented member 'event Func? A.E1'. // event Func A.E1 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation, "E1").WithArguments("event Func? A.E1").WithLocation(28, 26), // (29,26): warning CS8615: Nullability of reference types in type doesn't match implemented member 'event Func A.E2'. // event Func A.E2 { add {} remove {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation, "E2").WithArguments("event Func A.E2").WithLocation(29, 26) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_04() { var src = @" using System; interface I {} interface B { object M(); (object, object) M2(); I M3(); ref object M4(); ref readonly object M5(); Func P1 { get; set; } Func P2 { get; set; } object P3 { get; } event Func E1; event Func E2; } interface C : B { object? B.M() => null; // warn (object?, object?) B.M2() => throw null!; // warn I B.M3() => throw null!; // warn ref object? B.M4() => throw null!; // warn ref readonly object? B.M5() => throw null!; // warn Func? B.P1 { get => null!; set {} } // warn Func B.P2 { get => null!; set {} } // warn object? B.P3 => null!; // warn event Func? B.E1 { add {} remove {} } // ok event Func B.E2 { add {} remove {} } // ok } class D : C, B {} interface E : C, B {} "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,15): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'object B.M()'. // object? B.M() => null; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M").WithArguments("object B.M()").WithLocation(20, 15), // (21,26): warning CS8616: Nullability of reference types in return type doesn't match implemented member '(object, object) B.M2()'. // (object?, object?) B.M2() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M2").WithArguments("(object, object) B.M2()").WithLocation(21, 26), // (22,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'I B.M3()'. // I B.M3() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M3").WithArguments("I B.M3()").WithLocation(22, 18), // (23,19): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'ref object B.M4()'. // ref object? B.M4() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M4").WithArguments("ref object B.M4()").WithLocation(23, 19), // (24,28): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'ref readonly object B.M5()'. // ref readonly object? B.M5() => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M5").WithArguments("ref readonly object B.M5()").WithLocation(24, 28), // (25,26): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'Func B.P1.get'. // Func? B.P1 { get => null!; set {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("Func B.P1.get").WithLocation(25, 26), // (26,26): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'Func B.P2.get'. // Func B.P2 { get => null!; set {} } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("Func B.P2.get").WithLocation(26, 26), // (27,21): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'object B.P3.get'. // object? B.P3 => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "null!").WithArguments("object B.P3.get").WithLocation(27, 21) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_05() { var src = @" using System; interface A { Func? P1 { get => null!; private set {} } Func P2 { get => null!; private set {} } } class B : A { Func A.P1 { get; set; } = null!; Func A.P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,30): error CS0550: 'B.A.P1.set' adds an accessor not found in interface member 'A.P1' // Func A.P1 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("B.A.P1.set", "A.P1").WithLocation(11, 30), // (12,30): error CS0550: 'B.A.P2.set' adds an accessor not found in interface member 'A.P2' // Func A.P2 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("B.A.P2.set", "A.P2").WithLocation(12, 30) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_06() { var src = @" using System; interface A { Func? P1 { get => null!; private set {} } Func P2 { get => null!; private set {} } } class B : A { Func A.P1 { get; } = null!; Func A.P2 { get; } = null!; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Explicit_07() { var src = @" using System; interface A { Func? P1 { get; set; } Func P2 { get; set; } } class B : A { Func A.P1 { get; } = null!; Func A.P2 { get; } = null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): error CS0535: 'B' does not implement interface member 'A.P2.set' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.P2.set").WithLocation(9, 11), // (9,11): error CS0535: 'B' does not implement interface member 'A.P1.set' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.P1.set").WithLocation(9, 11), // (11,20): error CS0551: Explicit interface implementation 'B.A.P1' is missing accessor 'A.P1.set' // Func A.P1 { get; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P1").WithArguments("B.A.P1", "A.P1.set").WithLocation(11, 20), // (12,20): error CS0551: Explicit interface implementation 'B.A.P2' is missing accessor 'A.P2.set' // Func A.P2 { get; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P2").WithArguments("B.A.P2", "A.P2.set").WithLocation(12, 20) ); } [Fact] public void Implement_NullabilityCovariance_Explicit_08() { var src = @" using System; interface A { Func? P1 { get; } Func P2 { get; } } class B : A { Func A.P1 { get; set; } = null!; Func A.P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,30): error CS0550: 'B.A.P1.set' adds an accessor not found in interface member 'A.P1' // Func A.P1 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("B.A.P1.set", "A.P1").WithLocation(11, 30), // (12,30): error CS0550: 'B.A.P2.set' adds an accessor not found in interface member 'A.P2' // Func A.P2 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("B.A.P2.set", "A.P2").WithLocation(12, 30) ); } [Fact] public void Implement_NullabilityCovariance_Explict_09() { var src = @" using System; interface B { Func P1 { private get => null!; set{} } Func P2 { private get => null!; set{} } } class C : B { Func? B.P1 { get; set; } = null!; Func B.P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,26): error CS0550: 'C.B.P1.get' adds an accessor not found in interface member 'B.P1' // Func? B.P1 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("C.B.P1.get", "B.P1").WithLocation(11, 26), // (12,26): error CS0550: 'C.B.P2.get' adds an accessor not found in interface member 'B.P2' // Func B.P2 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("C.B.P2.get", "B.P2").WithLocation(12, 26) ); } [Fact] public void Implement_NullabilityCovariance_Explict_10() { var src = @" using System; interface B { Func P1 { private get => null!; set{} } Func P2 { private get => null!; set{} } } class C : B { Func? B.P1 { set{} } Func B.P2 { set{} } } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.NetStandardLatest, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Implement_NullabilityCovariance_Explict_11() { var src = @" using System; interface B { Func P1 { set; } Func P2 { set; } } class C : B { Func? B.P1 { get; set; } Func B.P2 { get; set; } = null!; } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,26): error CS0550: 'C.B.P1.get' adds an accessor not found in interface member 'B.P1' // Func? B.P1 { get; set; } Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("C.B.P1.get", "B.P1").WithLocation(11, 26), // (12,26): error CS0550: 'C.B.P2.get' adds an accessor not found in interface member 'B.P2' // Func B.P2 { get; set; } = null!; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("C.B.P2.get", "B.P2").WithLocation(12, 26) ); } [Fact] public void Implement_NullabilityCovariance_Explict_12() { var src = @" using System; interface B { Func P1 { get; set; } Func P2 { get; set; } } class C : B { Func? B.P1 { set {} } Func B.P2 { set {} } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): error CS0535: 'C' does not implement interface member 'B.P1.get' // class C : B Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "B").WithArguments("C", "B.P1.get").WithLocation(9, 11), // (9,11): error CS0535: 'C' does not implement interface member 'B.P2.get' // class C : B Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "B").WithArguments("C", "B.P2.get").WithLocation(9, 11), // (11,21): error CS0551: Explicit interface implementation 'C.B.P1' is missing accessor 'B.P1.get' // Func? B.P1 { set {} } Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P1").WithArguments("C.B.P1", "B.P1.get").WithLocation(11, 21), // (12,21): error CS0551: Explicit interface implementation 'C.B.P2' is missing accessor 'B.P2.get' // Func B.P2 { set {} } Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P2").WithArguments("C.B.P2", "B.P2.get").WithLocation(12, 21) ); } [Fact] public void Implement_NullabilityContravariance_Implicit_01() { var src = @" interface I {} interface A { void M(object o); void M2((object, object) t); void M3(I i); void M4(ref object o); void M5(out object o); void M6(in object o); object this[object o] { get; set; } string this[string s] { get; } string this[int[] a] { set; } } class B : A { public void M(object? o) { } public void M2((object?, object?) t) { } public void M3(I i) { } public void M4(ref object? o) { } // warn public void M5(out object? o) => throw null!; // warn public void M6(in object? o) { } public object? this[object? o] { get => null!; set { } } // warn public string this[string? s] => null!; public string this[int[]? a] { set { } } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,17): warning CS8614: Nullability of reference types in type of parameter 'o' of 'void B.M4(ref object? o)' doesn't match implicitly implemented member 'void A.M4(ref object o)'. // public void M4(ref object? o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M4").WithArguments("o", "void B.M4(ref object? o)", "void A.M4(ref object o)").WithLocation(20, 17), // (21,17): warning CS8614: Nullability of reference types in type of parameter 'o' of 'void B.M5(out object? o)' doesn't match implicitly implemented member 'void A.M5(out object o)'. // public void M5(out object? o) => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M5").WithArguments("o", "void B.M5(out object? o)", "void A.M5(out object o)").WithLocation(21, 17), // (23,38): warning CS8613: Nullability of reference types in return type of 'object? B.this[object? o].get' doesn't match implicitly implemented member 'object A.this[object o].get'. // public object? this[object? o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "get").WithArguments("object? B.this[object? o].get", "object A.this[object o].get").WithLocation(23, 38) ); } [Fact] public void Implement_NullabilityContravariance_Implicit_02() { var src = @" interface I {} interface B { void M(object? o); void M2((object?, object?) t); void M3(I i); void M4(ref object? o); void M5(out object? o); void M6(in object? o); object? this[object? o] { get; set; } string this[string? s] { get; } string this[int[]? a] { set; } } class C : B { public void M(object o) { } // warn public void M2((object, object) t) { } // warn public void M3(I i) { } // warn public void M4(ref object o) { } // warn public void M5(out object o) => throw null!; public void M6(in object o) { } // warn public object this[object o] { get => null!; set { } } // warn public string this[string s] => null!; // warn public string this[int[] a] { set { } } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,17): warning CS8614: Nullability of reference types in type of parameter 'o' of 'void C.M(object o)' doesn't match implicitly implemented member 'void B.M(object? o)'. // public void M(object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M").WithArguments("o", "void C.M(object o)", "void B.M(object? o)").WithLocation(17, 17), // (18,17): warning CS8614: Nullability of reference types in type of parameter 't' of 'void C.M2((object, object) t)' doesn't match implicitly implemented member 'void B.M2((object?, object?) t)'. // public void M2((object, object) t) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M2").WithArguments("t", "void C.M2((object, object) t)", "void B.M2((object?, object?) t)").WithLocation(18, 17), // (19,17): warning CS8614: Nullability of reference types in type of parameter 'i' of 'void C.M3(I i)' doesn't match implicitly implemented member 'void B.M3(I i)'. // public void M3(I i) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M3").WithArguments("i", "void C.M3(I i)", "void B.M3(I i)").WithLocation(19, 17), // (20,17): warning CS8614: Nullability of reference types in type of parameter 'o' of 'void C.M4(ref object o)' doesn't match implicitly implemented member 'void B.M4(ref object? o)'. // public void M4(ref object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M4").WithArguments("o", "void C.M4(ref object o)", "void B.M4(ref object? o)").WithLocation(20, 17), // (22,17): warning CS8614: Nullability of reference types in type of parameter 'o' of 'void C.M6(in object o)' doesn't match implicitly implemented member 'void B.M6(in object? o)'. // public void M6(in object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M6").WithArguments("o", "void C.M6(in object o)", "void B.M6(in object? o)").WithLocation(22, 17), // (23,50): warning CS8614: Nullability of reference types in type of parameter 'o' of 'void C.this[object o].set' doesn't match implicitly implemented member 'void B.this[object? o].set'. // public object this[object o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("o", "void C.this[object o].set", "void B.this[object? o].set").WithLocation(23, 50), // (23,50): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void C.this[object o].set' doesn't match implicitly implemented member 'void B.this[object? o].set'. // public object this[object o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("value", "void C.this[object o].set", "void B.this[object? o].set").WithLocation(23, 50), // (24,37): warning CS8614: Nullability of reference types in type of parameter 's' of 'string C.this[string s].get' doesn't match implicitly implemented member 'string B.this[string? s].get'. // public string this[string s] => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "null!").WithArguments("s", "string C.this[string s].get", "string B.this[string? s].get").WithLocation(24, 37), // (25,35): warning CS8614: Nullability of reference types in type of parameter 'a' of 'void C.this[int[] a].set' doesn't match implicitly implemented member 'void B.this[int[]? a].set'. // public string this[int[] a] { set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("a", "void C.this[int[] a].set", "void B.this[int[]? a].set").WithLocation(25, 35) ); } [Fact] public void Implement_NullabilityContravariance_Implicit_03() { var src = @" interface B { object? this[object? o] { get; set; } } class C { #nullable disable public virtual object this[object o] { get => null!; set { } } #nullable enable } class D : C, B { public override object this[object o] { get => null!; } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,45): warning CS8614: Nullability of reference types in type of parameter 'o' of 'object D.this[object o].get' doesn't match implicitly implemented member 'object? B.this[object? o].get'. // public override object this[object o] { get => null!; } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "get").WithArguments("o", "object D.this[object o].get", "object? B.this[object? o].get").WithLocation(14, 45) ); } [Fact] public void Implement_NullabilityContravariance_Implicit_04() { var src = @" interface B { object? this[object? o] { get; set; } } class C { public virtual object this[object o] { get => null!; set { } } } class D : C, B { #nullable disable public override object this[object o #nullable enable ] { set {} } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,14): warning CS8614: Nullability of reference types in type of parameter 'o' of 'object C.this[object o].get' doesn't match implicitly implemented member 'object? B.this[object? o].get'. // class D : C, B Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "B").WithArguments("o", "object C.this[object o].get", "object? B.this[object? o].get").WithLocation(10, 14) ); } [Fact] public void Implement_NullabilityContravariance_Explicit_01() { var src = @" interface I {} interface A { void M(object o); void M2((object, object) t); void M3(I i); void M4(ref object o); void M5(out object o); void M6(in object o); object this[object o] { get; set; } string this[string s] { get; } string this[int[] a] { set; } } class B : A { void A.M(object? o) { } void A.M2((object?, object?) t) { } void A.M3(I i) { } void A.M4(ref object? o) { } // warn void A.M5(out object? o) => throw null!; // warn void A.M6(in object? o) { } object? A.this[object? o] { get => null!; set { } } // warn string A.this[string? s] => null!; string A.this[int[]? a] { set { } } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,12): warning CS8617: Nullability of reference types in type of parameter 'o' doesn't match implemented member 'void A.M4(ref object o)'. // void A.M4(ref object? o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M4").WithArguments("o", "void A.M4(ref object o)").WithLocation(20, 12), // (21,12): warning CS8617: Nullability of reference types in type of parameter 'o' doesn't match implemented member 'void A.M5(out object o)'. // void A.M5(out object? o) => throw null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M5").WithArguments("o", "void A.M5(out object o)").WithLocation(21, 12), // (23,33): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'object A.this[object o].get'. // object? A.this[object? o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "get").WithArguments("object A.this[object o].get").WithLocation(23, 33) ); } [Fact] public void Implement_NullabilityContravariance_Explicit_02() { var src = @" interface I {} interface B { void M(object? o); void M2((object?, object?) t); void M3(I i); void M4(ref object? o); void M5(out object? o); void M6(in object? o); object? this[object? o] { get; set; } string this[string? s] { get; } string this[int[]? a] { set; } } class C : B { void B.M(object o) { } // warn void B.M2((object, object) t) { } // warn void B.M3(I i) { } // warn void B.M4(ref object o) { } // warn void B.M5(out object o) => throw null!; void B.M6(in object o) { } // warn object B.this[object o] { get => null!; set { } } // warn string B.this[string s] => null!; // warn string B.this[int[] a] { set { } } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,12): warning CS8617: Nullability of reference types in type of parameter 'o' doesn't match implemented member 'void B.M(object? o)'. // void B.M(object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M").WithArguments("o", "void B.M(object? o)").WithLocation(17, 12), // (18,12): warning CS8617: Nullability of reference types in type of parameter 't' doesn't match implemented member 'void B.M2((object?, object?) t)'. // void B.M2((object, object) t) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M2").WithArguments("t", "void B.M2((object?, object?) t)").WithLocation(18, 12), // (19,12): warning CS8617: Nullability of reference types in type of parameter 'i' doesn't match implemented member 'void B.M3(I i)'. // void B.M3(I i) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M3").WithArguments("i", "void B.M3(I i)").WithLocation(19, 12), // (20,12): warning CS8617: Nullability of reference types in type of parameter 'o' doesn't match implemented member 'void B.M4(ref object? o)'. // void B.M4(ref object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M4").WithArguments("o", "void B.M4(ref object? o)").WithLocation(20, 12), // (22,12): warning CS8617: Nullability of reference types in type of parameter 'o' doesn't match implemented member 'void B.M6(in object? o)'. // void B.M6(in object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "M6").WithArguments("o", "void B.M6(in object? o)").WithLocation(22, 12), // (23,45): warning CS8617: Nullability of reference types in type of parameter 'o' doesn't match implemented member 'void B.this[object? o].set'. // object B.this[object o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("o", "void B.this[object? o].set").WithLocation(23, 45), // (23,45): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void B.this[object? o].set'. // object B.this[object o] { get => null!; set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("value", "void B.this[object? o].set").WithLocation(23, 45), // (24,32): warning CS8617: Nullability of reference types in type of parameter 's' doesn't match implemented member 'string B.this[string? s].get'. // string B.this[string s] => null!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "null!").WithArguments("s", "string B.this[string? s].get").WithLocation(24, 32), // (25,30): warning CS8617: Nullability of reference types in type of parameter 'a' doesn't match implemented member 'void B.this[int[]? a].set'. // string B.this[int[] a] { set { } } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("a", "void B.this[int[]? a].set").WithLocation(25, 30) ); } [Fact] public void Partial_NullabilityContravariance_01() { var src = @" interface I {} partial class A { partial void M(object o); partial void M2((object, object) t); partial void M3(I i); partial void M4(ref object o); partial void M6(in object o); } partial class A { partial void M(object? o) { } partial void M2((object?, object?) t) { } partial void M3(I i) { } partial void M4(ref object? o) { } // warn partial void M6(in object? o) { } } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,18): warning CS8611: Nullability of reference types in type of parameter 'o' doesn't match partial method declaration. // partial void M4(ref object? o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M4").WithArguments("o").WithLocation(16, 18) ); } [Fact] public void Partial_NullabilityContravariance_02() { var src = @" interface I {} partial class B { partial void M(object? o); partial void M2((object?, object?) t); partial void M3(I i); partial void M4(ref object? o); partial void M6(in object? o); } partial class B { partial void M(object o) { } // warn partial void M2((object, object) t) { } // warn partial void M3(I i) { } // warn partial void M4(ref object o) { } // warn partial void M6(in object o) { } // warn } "; var comp = CreateCompilation(src, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,18): warning CS8611: Nullability of reference types in type of parameter 'o' doesn't match partial method declaration. // partial void M(object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M").WithArguments("o").WithLocation(13, 18), // (14,18): warning CS8611: Nullability of reference types in type of parameter 't' doesn't match partial method declaration. // partial void M2((object, object) t) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M2").WithArguments("t").WithLocation(14, 18), // (15,18): warning CS8611: Nullability of reference types in type of parameter 'i' doesn't match partial method declaration. // partial void M3(I i) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M3").WithArguments("i").WithLocation(15, 18), // (16,18): warning CS8611: Nullability of reference types in type of parameter 'o' doesn't match partial method declaration. // partial void M4(ref object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M4").WithArguments("o").WithLocation(16, 18), // (17,18): warning CS8611: Nullability of reference types in type of parameter 'o' doesn't match partial method declaration. // partial void M6(in object o) { } // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M6").WithArguments("o").WithLocation(17, 18) ); } [Fact] public void Implementing_07() { var source = @" class C { public static void Main() { } } interface IA { void M1(string[] x); void M2(T[] x) where T : class; void M3(T?[]? x) where T : class; } class B : IA { public void M1(string?[] x) { } public void M2(T?[] x) where T : class { } public void M3(T?[]? x) where T : class { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var ia = compilation.GetTypeByMetadataName("IA"); var b = compilation.GetTypeByMetadataName("B"); foreach (var memberName in new[] { "M1", "M2" }) { var member = ia.GetMember(memberName); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.False(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } { var member = ia.GetMember("M3"); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.True(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } [Fact] public void Implementing_08() { var source = @" class C { public static void Main() { } } interface IA { void M1(string[] x); void M2(T[] x) where T : class; void M3(T?[]? x) where T : class; } class B : IA { void IA.M1(string?[] x) { } void IA.M2(T?[] x) { } void IA.M3(T?[]? x) { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (20,13): error CS0539: 'B.M2(T?[])' in explicit interface declaration is not found among members of the interface that can be implemented // void IA.M2(T?[] x) Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M2").WithArguments("B.M2(T?[])").WithLocation(20, 13), // (24,13): error CS0539: 'B.M3(T?[]?)' in explicit interface declaration is not found among members of the interface that can be implemented // void IA.M3(T?[]? x) Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("B.M3(T?[]?)").WithLocation(24, 13), // (14,11): error CS0535: 'B' does not implement interface member 'IA.M3(T?[]?)' // class B : IA Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IA").WithArguments("B", "IA.M3(T?[]?)").WithLocation(14, 11), // (14,11): error CS0535: 'B' does not implement interface member 'IA.M2(T[])' // class B : IA Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IA").WithArguments("B", "IA.M2(T[])").WithLocation(14, 11), // (20,24): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // void IA.M2(T?[] x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(20, 24), // (24,25): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // void IA.M3(T?[]? x) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(24, 25)); } [Fact] public void Overriding_20() { var source = @" class C { public static void Main() { } } abstract class A1 { public abstract int this[string?[] x] {get; set;} } abstract class A2 { public abstract int this[string[] x] {get; set;} } abstract class A3 { public abstract int this[string?[]? x] {get; set;} } class B1 : A1 { public override int this[string[] x] { get {throw new System.NotImplementedException();} set {} // 1 } } class B2 : A2 { public override int this[string[]? x] { get {throw new System.NotImplementedException();} set {} } } class B3 : A3 { public override int this[string?[]? x] { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (27,9): warning CS8610: Nullability of reference types in type of parameter 'x' doesn't match overridden member. // set {} // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "set").WithArguments("x").WithLocation(27, 9) ); foreach (string typeName in new[] { "B1", "B2" }) { foreach (var member in compilation.GetTypeByMetadataName(typeName).GetMembers().OfType()) { Assert.False(member.Parameters[0].TypeWithAnnotations.Equals(member.OverriddenProperty.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } foreach (var member in compilation.GetTypeByMetadataName("B3").GetMembers().OfType()) { Assert.True(member.Parameters[0].TypeWithAnnotations.Equals(member.OverriddenProperty.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "A1", "A2", "A3", "B1", "B2", "B3" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var property in type.GetMembers().OfType()) { Assert.True(property.TypeWithAnnotations.Equals(property.GetMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(property.TypeWithAnnotations.Equals(property.SetMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Implementing_09() { var source = @" class C { public static void Main() { } } interface IA1 { int this[string?[] x] {get; set;} } interface IA2 { int this[string[] x] {get; set;} } interface IA3 { int this[string?[]? x] {get; set;} } class B1 : IA1 { public int this[string[] x] { get {throw new System.NotImplementedException();} set {} // 1 } } class B2 : IA2 { public int this[string[]? x] // 2 { get {throw new System.NotImplementedException();} set {} } } class B3 : IA3 { public int this[string?[]? x] // 3 { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (27,9): warning CS8614: Nullability of reference types in type of parameter 'x' of 'void B1.this[string[] x].set' doesn't match implicitly implemented member 'void IA1.this[string?[] x].set'. // set {} // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "set").WithArguments("x", "void B1.this[string[] x].set", "void IA1.this[string?[] x].set").WithLocation(27, 9) ); foreach (string[] typeName in new[] { new[] { "IA1", "B1" }, new[] { "IA2", "B2" } }) { var implemented = compilation.GetTypeByMetadataName(typeName[0]).GetMembers().OfType().Single(); var implementing = (PropertySymbol)compilation.GetTypeByMetadataName(typeName[1]).FindImplementationForInterfaceMember(implemented); Assert.False(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } { var implemented = compilation.GetTypeByMetadataName("IA3").GetMembers().OfType().Single(); var implementing = (PropertySymbol)compilation.GetTypeByMetadataName("B3").FindImplementationForInterfaceMember(implemented); Assert.True(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "IA1", "IA2", "IA3", "B1", "B2", "B3" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var property in type.GetMembers().OfType()) { Assert.True(property.TypeWithAnnotations.Equals(property.GetMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(property.TypeWithAnnotations.Equals(property.SetMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Implementing_10() { var source = @" class C { public static void Main() { } } interface IA1 { int this[string?[] x] {get; set;} } interface IA2 { int this[string[] x] {get; set;} } interface IA3 { int this[string?[]? x] {get; set;} } class B1 : IA1 { int IA1.this[string[] x] { get {throw new System.NotImplementedException();} set {} // 1 } } class B2 : IA2 { int IA2.this[string[]? x] // 2 { get {throw new System.NotImplementedException();} set {} } } class B3 : IA3 { int IA3.this[string?[]? x] // 3 { get {throw new System.NotImplementedException();} set {} } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (27,9): warning CS8617: Nullability of reference types in type of parameter 'x' doesn't match implemented member 'void IA1.this[string?[] x].set'. // set {} // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "set").WithArguments("x", "void IA1.this[string?[] x].set").WithLocation(27, 9) ); foreach (string[] typeName in new[] { new[] { "IA1", "B1" }, new[] { "IA2", "B2" } }) { var implemented = compilation.GetTypeByMetadataName(typeName[0]).GetMembers().OfType().Single(); var implementing = (PropertySymbol)compilation.GetTypeByMetadataName(typeName[1]).FindImplementationForInterfaceMember(implemented); Assert.False(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } { var implemented = compilation.GetTypeByMetadataName("IA3").GetMembers().OfType().Single(); var implementing = (PropertySymbol)compilation.GetTypeByMetadataName("B3").FindImplementationForInterfaceMember(implemented); Assert.True(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } foreach (string typeName in new[] { "IA1", "IA2", "IA3", "B1", "B2", "B3" }) { var type = compilation.GetTypeByMetadataName(typeName); foreach (var property in type.GetMembers().OfType()) { Assert.True(property.TypeWithAnnotations.Equals(property.GetMethod.ReturnTypeWithAnnotations, TypeCompareKind.ConsiderEverything)); Assert.True(property.TypeWithAnnotations.Equals(property.SetMethod.Parameters.Last().TypeWithAnnotations, TypeCompareKind.ConsiderEverything)); } } } [Fact] public void Implementing_11() { var source = @" public interface I1 { void M(); } public class A {} public interface I2 : I1 { } public interface I3 : I1 { } public class C1 : I2, I1 { void I1.M(){} void I1.M(){} } public class C2 : I1, I2 { void I1.M(){} void I1.M(){} } public class C3 : I1, I1 { void I1.M(){} void I1.M(){} } public class C4 : I2, I3 { void I1.M(){} void I1.M(){} } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,14): warning CS8645: 'I1' is already listed in the interface list on type 'C1' with different nullability of reference types. // public class C1 : I2, I1 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C1").WithArguments("I1", "C1").WithLocation(11, 14), // (11,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C1 : I2, I1 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("I1.M()").WithLocation(11, 14), // (11,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C1 : I2, I1 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("I1.M()").WithLocation(11, 14), // (17,14): warning CS8645: 'I1' is already listed in the interface list on type 'C2' with different nullability of reference types. // public class C2 : I1, I2 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C2").WithArguments("I1", "C2").WithLocation(17, 14), // (17,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C2 : I1, I2 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C2").WithArguments("I1.M()").WithLocation(17, 14), // (17,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C2 : I1, I2 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C2").WithArguments("I1.M()").WithLocation(17, 14), // (23,14): warning CS8645: 'I1' is already listed in the interface list on type 'C3' with different nullability of reference types. // public class C3 : I1, I1 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C3").WithArguments("I1", "C3").WithLocation(23, 14), // (23,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C3 : I1, I1 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C3").WithArguments("I1.M()").WithLocation(23, 14), // (23,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C3 : I1, I1 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C3").WithArguments("I1.M()").WithLocation(23, 14), // (29,14): warning CS8645: 'I1' is already listed in the interface list on type 'C4' with different nullability of reference types. // public class C4 : I2, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C4").WithArguments("I1", "C4").WithLocation(29, 14), // (29,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C4 : I2, I3 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C4").WithArguments("I1.M()").WithLocation(29, 14), // (29,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C4 : I2, I3 Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C4").WithArguments("I1.M()").WithLocation(29, 14) ); var c1 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C1"); var c1Interfaces = c1.Interfaces; var c1AllInterfaces = c1.AllInterfaces; Assert.Equal(2, c1Interfaces.Length); Assert.Equal(3, c1AllInterfaces.Length); Assert.Equal("I2", c1Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c1AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c1); var c2 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C2"); var c2Interfaces = c2.Interfaces; var c2AllInterfaces = c2.AllInterfaces; Assert.Equal(2, c2Interfaces.Length); Assert.Equal(3, c2AllInterfaces.Length); Assert.Equal("I1", c2Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c2Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c2AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c2); var c3 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C3"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; Assert.Equal(2, c3Interfaces.Length); Assert.Equal(2, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c3); var c4 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C4"); var c4Interfaces = c4.Interfaces; var c4AllInterfaces = c4.AllInterfaces; Assert.Equal(2, c4Interfaces.Length); Assert.Equal(4, c4AllInterfaces.Length); Assert.Equal("I2", c4Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I3", c4Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c4AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c4AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I3", c4AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c4AllInterfaces[3].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c4); void assertExplicitInterfaceImplementations(INamedTypeSymbol c) { var members = c.GetMembers("I1.M"); Assert.Equal(2, members.Length); var cMabImplementations = ((IMethodSymbol)members[0]).ExplicitInterfaceImplementations; Assert.Equal(1, cMabImplementations.Length); Assert.Equal("void I1.M()", cMabImplementations[0].ToTestDisplayString(includeNonNullable: true)); var cMcdImplementations = ((IMethodSymbol)members[1]).ExplicitInterfaceImplementations; Assert.Equal(1, cMcdImplementations.Length); Assert.Equal("void I1.M()", cMcdImplementations[0].ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void Implementing_12() { var source = @" public interface I1 { void M1(); void M2(); } public class A {} public class C1 : I1 { public void M1() => System.Console.WriteLine(""C1.M1""); void I1.M2() => System.Console.WriteLine(""C1.M2""); } public class C2 : C1, I1 { new public void M1() => System.Console.WriteLine(""C2.M1""); void I1.M2() => System.Console.WriteLine(""C2.M2""); static void Main() { var x = (C1)new C2(); var y = (I1)x; y.M1(); y.M2(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics(); Action validate = (m) => { bool isMetadata = m is PEModuleSymbol; var c1 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C1"); var c1Interfaces = c1.Interfaces; var c1AllInterfaces = c1.AllInterfaces; Assert.Equal(1, c1Interfaces.Length); Assert.Equal(1, c1AllInterfaces.Length); Assert.Equal("I1", c1Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); var c2 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C2"); var c2Interfaces = c2.Interfaces; var c2AllInterfaces = c2.AllInterfaces; Assert.Equal(1, c2Interfaces.Length); Assert.Equal(2, c2AllInterfaces.Length); Assert.Equal("I1", c2Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("void C2.M1()", c2.FindImplementationForInterfaceMember(((TypeSymbol)c2Interfaces[0]).GetMember("M1")).ToTestDisplayString(includeNonNullable: true)); Assert.Equal("void C2.M1()", c2.FindImplementationForInterfaceMember(((TypeSymbol)c1Interfaces[0]).GetMember("M1")).ToTestDisplayString(includeNonNullable: true)); var m2 = (IMethodSymbol)((TypeSymbol)c2).GetMember("I1.M2"); var m2Implementations = m2.ExplicitInterfaceImplementations; Assert.Equal(1, m2Implementations.Length); Assert.Equal(isMetadata ? "void I1.M2()" : "void I1.M2()", m2Implementations[0].ToTestDisplayString(includeNonNullable: true)); Assert.Same(m2, c2.FindImplementationForInterfaceMember(((TypeSymbol)c2Interfaces[0]).GetMember("M2"))); Assert.Same(m2, c2.FindImplementationForInterfaceMember(((TypeSymbol)c1Interfaces[0]).GetMember("M2"))); }; CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate, expectedOutput: @"C2.M1 C2.M2 "); } [Fact] public void Implementing_13() { var source = @" public interface I1 { void M1(); void M2(); } public class A {} public class C1 : I1 { public void M1() => System.Console.WriteLine(""C1.M1""); void I1.M2() => System.Console.WriteLine(""C1.M2""); public virtual void M2() {} } public class C2 : C1, I1 { static void Main() { var x = (C1)new C2(); var y = (I1)x; y.M1(); y.M2(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (17,23): warning CS8644: 'C2' does not implement interface member 'I1.M2()'. Nullability of reference types in interface implemented by the base type doesn't match. // public class C2 : C1, I1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I1").WithArguments("C2", "I1.M2()").WithLocation(17, 23) ); Action validate = (m) => { bool isMetadata = m is PEModuleSymbol; var c1 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C1"); var c1Interfaces = c1.Interfaces; var c1AllInterfaces = c1.AllInterfaces; Assert.Equal(1, c1Interfaces.Length); Assert.Equal(1, c1AllInterfaces.Length); Assert.Equal("I1", c1Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); var c2 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C2"); var c2Interfaces = c2.Interfaces; var c2AllInterfaces = c2.AllInterfaces; Assert.Equal(1, c2Interfaces.Length); Assert.Equal(2, c2AllInterfaces.Length); Assert.Equal("I1", c2Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("void C1.M1()", c2.FindImplementationForInterfaceMember(((TypeSymbol)c2Interfaces[0]).GetMember("M1")).ToTestDisplayString(includeNonNullable: true)); Assert.Equal("void C1.M1()", c2.FindImplementationForInterfaceMember(((TypeSymbol)c1Interfaces[0]).GetMember("M1")).ToTestDisplayString(includeNonNullable: true)); var m2 = (IMethodSymbol)((TypeSymbol)c1).GetMember("I1.M2"); var m2Implementations = m2.ExplicitInterfaceImplementations; Assert.Equal(1, m2Implementations.Length); Assert.Equal(isMetadata ? "void I1.M2()" : "void I1.M2()", m2Implementations[0].ToTestDisplayString(includeNonNullable: true)); Assert.Same(m2, c2.FindImplementationForInterfaceMember(((TypeSymbol)c2Interfaces[0]).GetMember("M2"))); Assert.Same(m2, c2.FindImplementationForInterfaceMember(((TypeSymbol)c1Interfaces[0]).GetMember("M2"))); }; CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate, expectedOutput: @"C1.M1 C1.M2 "); } [Fact] public void Implementing_14() { var source = @" public interface I1 { void M1(); } public class A {} public class C1 : I1 { } public class C2 : C1, I1 { } public class C3 : C1, I1 { } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,19): error CS0535: 'C1' does not implement interface member 'I1.M1()' // public class C1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("C1", "I1.M1()").WithLocation(9, 19), // (13,23): warning CS8644: 'C2' does not implement interface member 'I1.M1()'. Nullability of reference types in interface implemented by the base type doesn't match. // public class C2 : C1, I1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I1").WithArguments("C2", "I1.M1()").WithLocation(13, 23) ); } [Fact] public void Implementing_15() { var source1 = @" public interface I1 { void M1(); } public class A {} public class C1 : I1 { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (9,19): error CS0535: 'C1' does not implement interface member 'I1.M1()' // public class C1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("C1", "I1.M1()").WithLocation(9, 19) ); var source2 = @" public class C2 : C1, I1 { } public class C3 : C1, I1 { } "; var comp2 = CreateCompilation(source2, references: new[] { comp1.ToMetadataReference() }, options: WithNonNullTypesTrue()); comp2.VerifyDiagnostics( // (2,23): warning CS8644: 'C2' does not implement interface member 'I1.M1()'. Nullability of reference types in interface implemented by the base type doesn't match. // public class C2 : C1, I1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I1").WithArguments("C2", "I1.M1()").WithLocation(2, 23) ); } [Fact] public void Implementing_16() { var source = @" public interface I1 { void M(); } public interface I2 : I1 where I2T : class { } public interface I3 : I1 where I3T : class { } public class C1 : I2, I1 where T : class { void I1.M(){} void I1.M(){} } public class C2 : I1, I2 where T : class { void I1.M(){} void I1.M(){} } public class C3 : I1, I1 where T : class { void I1.M(){} void I1.M(){} } public class C4 : I2, I3 where T : class { void I1.M(){} void I1.M(){} } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,14): warning CS8645: 'I1' is already listed in the interface list on type 'C1' with different nullability of reference types. // public class C1 : I2, I1 where T : class Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C1").WithArguments("I1", "C1").WithLocation(10, 14), // (10,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C1 : I2, I1 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("I1.M()").WithLocation(10, 14), // (10,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C1 : I2, I1 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("I1.M()").WithLocation(10, 14), // (16,14): warning CS8645: 'I1' is already listed in the interface list on type 'C2' with different nullability of reference types. // public class C2 : I1, I2 where T : class Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C2").WithArguments("I1", "C2").WithLocation(16, 14), // (16,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C2 : I1, I2 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C2").WithArguments("I1.M()").WithLocation(16, 14), // (16,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C2 : I1, I2 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C2").WithArguments("I1.M()").WithLocation(16, 14), // (22,14): warning CS8645: 'I1' is already listed in the interface list on type 'C3' with different nullability of reference types. // public class C3 : I1, I1 where T : class Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C3").WithArguments("I1", "C3").WithLocation(22, 14), // (22,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C3 : I1, I1 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C3").WithArguments("I1.M()").WithLocation(22, 14), // (22,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C3 : I1, I1 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C3").WithArguments("I1.M()").WithLocation(22, 14), // (28,14): warning CS8645: 'I1' is already listed in the interface list on type 'C4' with different nullability of reference types. // public class C4 : I2, I3 where T : class Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C4").WithArguments("I1", "C4").WithLocation(28, 14), // (28,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C4 : I2, I3 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C4").WithArguments("I1.M()").WithLocation(28, 14), // (28,14): error CS8646: 'I1.M()' is explicitly implemented more than once. // public class C4 : I2, I3 where T : class Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C4").WithArguments("I1.M()").WithLocation(28, 14) ); var c1 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C1`1"); var c1Interfaces = c1.Interfaces; var c1AllInterfaces = c1.AllInterfaces; Assert.Equal(2, c1Interfaces.Length); Assert.Equal(3, c1AllInterfaces.Length); Assert.Equal("I2", c1Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c1AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c1AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c1); var c2 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C2`1"); var c2Interfaces = c2.Interfaces; var c2AllInterfaces = c2.AllInterfaces; Assert.Equal(2, c2Interfaces.Length); Assert.Equal(3, c2AllInterfaces.Length); Assert.Equal("I1", c2Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c2Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c2AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c2AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c2); var c3 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C3`1"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; Assert.Equal(2, c3Interfaces.Length); Assert.Equal(2, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c3); var c4 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C4`1"); var c4Interfaces = c4.Interfaces; var c4AllInterfaces = c4.AllInterfaces; Assert.Equal(2, c4Interfaces.Length); Assert.Equal(4, c4AllInterfaces.Length); Assert.Equal("I2", c4Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I3", c4Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c4AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c4AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I3", c4AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c4AllInterfaces[3].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c4); void assertExplicitInterfaceImplementations(INamedTypeSymbol c) { var members = c.GetMembers("I1.M"); Assert.Equal(2, members.Length); var cMabImplementations = ((IMethodSymbol)members[0]).ExplicitInterfaceImplementations; Assert.Equal(1, cMabImplementations.Length); Assert.Equal("void I1.M()", cMabImplementations[0].ToTestDisplayString(includeNonNullable: true)); var cMcdImplementations = ((IMethodSymbol)members[1]).ExplicitInterfaceImplementations; Assert.Equal(1, cMcdImplementations.Length); Assert.Equal("void I1.M()", cMcdImplementations[0].ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void Implementing_17() { var source = @" public interface I1 { void M(); } public class C3 : I1, I1 where T : class where U : class { void I1.M(){} void I1.M(){} } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,14): error CS0695: 'C3' cannot implement both 'I1' and 'I1' because they may unify for some type parameter substitutions // public class C3 : I1, I1 where T : class where U : class Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3", "I1", "I1").WithLocation(7, 14) ); var c3 = (INamedTypeSymbol)comp.GetTypeByMetadataName("C3`2"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; Assert.Equal(2, c3Interfaces.Length); Assert.Equal(2, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); assertExplicitInterfaceImplementations(c3); void assertExplicitInterfaceImplementations(INamedTypeSymbol c) { var cMabImplementations = ((IMethodSymbol)((TypeSymbol)c).GetMember("I1.M")).ExplicitInterfaceImplementations; Assert.Equal(1, cMabImplementations.Length); Assert.Equal("void I1.M()", cMabImplementations[0].ToTestDisplayString(includeNonNullable: true)); var cMcdImplementations = ((IMethodSymbol)((TypeSymbol)c).GetMember("I1.M")).ExplicitInterfaceImplementations; Assert.Equal(1, cMcdImplementations.Length); Assert.Equal("void I1.M()", cMcdImplementations[0].ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void Implementing_18() { var source = @" public interface I1 { void M(); } public class A {} public class C3 : I1 { void I1.M() { System.Console.WriteLine(""C3.M""); } static void Main() { var x = new C3(); ((I1)x).M(); ((I1)x).M(); } } public class C4 : I1 { void I1.M(){} } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (11,10): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void I1.M() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "I1").WithLocation(11, 10) ); Action validate = (ModuleSymbol m) => { bool isMetadata = m is PEModuleSymbol; var c3 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C3"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; Assert.Equal(1, c3Interfaces.Length); Assert.Equal(1, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); var method = (IMethodSymbol)((TypeSymbol)c3).GetMember("I1.M"); Assert.Equal("I1.M", method.Name); var mImplementations = method.ExplicitInterfaceImplementations; Assert.Equal(1, mImplementations.Length); Assert.Equal(isMetadata ? "void I1.M()" : "void I1.M()", mImplementations[0].ToTestDisplayString(includeNonNullable: true)); Assert.Same(method, c3.FindImplementationForInterfaceMember(((TypeSymbol)c3Interfaces[0]).GetMember("M"))); Assert.Same(method, c3.FindImplementationForInterfaceMember(mImplementations[0])); Assert.Same(method, c3.FindImplementationForInterfaceMember(m.GlobalNamespace.GetTypeMember("C4").InterfacesNoUseSiteDiagnostics()[0].GetMember("M"))); }; CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate, expectedOutput: @"C3.M C3.M"); } [Fact] public void Implementing_19() { var source = @" public interface I1 { void M(); } public class A {} public class C3 : I1, I1 { void I1.M() { System.Console.WriteLine(""C3.M""); } static void Main() { var x = new C3(); ((I1)x).M(); ((I1)x).M(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (9,14): warning CS8645: 'I1' is already listed in the interface list on type 'C3' with different nullability of reference types. // public class C3 : I1, I1 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C3").WithArguments("I1", "C3").WithLocation(9, 14) ); Action validate = (ModuleSymbol m) => { bool isMetadata = m is PEModuleSymbol; var c3 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C3"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; if (isMetadata) { Assert.Equal(1, c3Interfaces.Length); Assert.Equal(1, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); } else { Assert.Equal(2, c3Interfaces.Length); Assert.Equal(2, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); } var method = (IMethodSymbol)((TypeSymbol)c3).GetMember("I1.M"); Assert.Equal("I1.M", method.Name); var mImplementations = method.ExplicitInterfaceImplementations; Assert.Equal(1, mImplementations.Length); Assert.Equal(isMetadata ? "void I1.M()" : "void I1.M()", mImplementations[0].ToTestDisplayString(includeNonNullable: true)); Assert.Same(method, c3.FindImplementationForInterfaceMember(((TypeSymbol)c3Interfaces[0]).GetMember("M"))); Assert.Same(method, c3.FindImplementationForInterfaceMember(mImplementations[0])); }; CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate, expectedOutput: @"C3.M C3.M"); } [Fact] public void Implementing_20() { var source = @" public interface I1 { void M(); } public class A {} public interface I2 : I1 {} public class C3 : I2, I1 { void I1.M() { System.Console.WriteLine(""C3.M""); } static void Main() { var x = new C3(); ((I1)x).M(); ((I1)x).M(); } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (12,14): warning CS8645: 'I1' is already listed in the interface list on type 'C3' with different nullability of reference types. // public class C3 : I2, I1 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C3").WithArguments("I1", "C3").WithLocation(12, 14) ); Action validate = (ModuleSymbol m) => { bool isMetadata = m is PEModuleSymbol; var c3 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C3"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; if (isMetadata) { Assert.Equal(2, c3Interfaces.Length); Assert.Equal(2, c3AllInterfaces.Length); Assert.Equal("I2", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); } else { Assert.Equal(2, c3Interfaces.Length); Assert.Equal(3, c3AllInterfaces.Length); Assert.Equal("I2", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I2", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[2].ToTestDisplayString(includeNonNullable: true)); } var method = (IMethodSymbol)((TypeSymbol)c3).GetMember("I1.M"); Assert.Equal("I1.M", method.Name); var mImplementations = method.ExplicitInterfaceImplementations; Assert.Equal(1, mImplementations.Length); Assert.Equal(isMetadata ? "void I1.M()" : "void I1.M()", mImplementations[0].ToTestDisplayString(includeNonNullable: true)); Assert.Same(method, c3.FindImplementationForInterfaceMember(((TypeSymbol)c3Interfaces[1]).GetMember("M"))); Assert.Same(method, c3.FindImplementationForInterfaceMember(mImplementations[0])); }; CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate, expectedOutput: @"C3.M C3.M"); } [Fact] public void Implementing_21() { var source = @" public interface I1 { void M(); } public class A {} public partial class C3 : I1 { void I1.M() { System.Console.WriteLine(""C3.M""); } static void Main() { var x = new C3(); ((I1)x).M(); ((I1)x).M(); } } public partial class C3 : I1 {} "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(TestOptions.DebugExe)); comp.VerifyDiagnostics( // (9,22): warning CS8645: 'I1' is already listed in the interface list on type 'C3' with different nullability of reference types. // public partial class C3 : I1 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C3").WithArguments("I1", "C3").WithLocation(9, 22) ); Action validate = (ModuleSymbol m) => { bool isMetadata = m is PEModuleSymbol; var c3 = (INamedTypeSymbol)m.GlobalNamespace.GetTypeMember("C3"); var c3Interfaces = c3.Interfaces; var c3AllInterfaces = c3.AllInterfaces; if (isMetadata) { Assert.Equal(1, c3Interfaces.Length); Assert.Equal(1, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); } else { Assert.Equal(2, c3Interfaces.Length); Assert.Equal(2, c3AllInterfaces.Length); Assert.Equal("I1", c3Interfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3Interfaces[1].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[0].ToTestDisplayString(includeNonNullable: true)); Assert.Equal("I1", c3AllInterfaces[1].ToTestDisplayString(includeNonNullable: true)); } var method = (IMethodSymbol)((TypeSymbol)c3).GetMember("I1.M"); Assert.Equal("I1.M", method.Name); var mImplementations = method.ExplicitInterfaceImplementations; Assert.Equal(1, mImplementations.Length); Assert.Equal(isMetadata ? "void I1.M()" : "void I1.M()", mImplementations[0].ToTestDisplayString(includeNonNullable: true)); Assert.Same(method, c3.FindImplementationForInterfaceMember(((TypeSymbol)c3Interfaces[0]).GetMember("M"))); Assert.Same(method, c3.FindImplementationForInterfaceMember(mImplementations[0])); }; CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate, expectedOutput: @"C3.M C3.M"); } [Fact] public void Implementing_23() { var source = @" class C { public static void Main() { } } interface IA { void M1(string[] x); void M2(T[] x) where T : class; void M3(T?[]? x) where T : class; } class B : IA { void IA.M1(string?[] x) { } void IA.M2(T?[] x) where T : class { } void IA.M3(T?[]? x) where T : class { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); var ia = compilation.GetTypeByMetadataName("IA"); var b = compilation.GetTypeByMetadataName("B"); foreach (var memberName in new[] { "M1", "M2" }) { var member = ia.GetMember(memberName); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.False(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } { var member = ia.GetMember("M3"); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.True(implementing.Parameters[0].TypeWithAnnotations.Equals(implemented.Parameters[0].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } [Fact] public void Implementing_24() { var source = @" class C { public static void Main() { } } interface IA { string[] M1(); T[] M2() where T : class; T?[]? M3() where T : class; } class B : IA { string?[] IA.M1() { return new string?[] {}; } S?[] IA.M2() where S : class { return new S?[] {}; } S?[]? IA.M3() where S : class { return new S?[] {}; } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (23,13): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'S[] IA.M2()'. // S?[] IA.M2() where S : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M2").WithArguments("S[] IA.M2()").WithLocation(23, 13), // (18,18): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'string[] IA.M1()'. // string?[] IA.M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "M1").WithArguments("string[] IA.M1()").WithLocation(18, 18) ); var ia = compilation.GetTypeByMetadataName("IA"); var b = compilation.GetTypeByMetadataName("B"); foreach (var memberName in new[] { "M1", "M2" }) { var member = ia.GetMember(memberName); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.False(implementing.ReturnTypeWithAnnotations.Equals(implemented.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } { var member = ia.GetMember("M3"); var implementing = (MethodSymbol)b.FindImplementationForInterfaceMember(member); var implemented = member.ConstructIfGeneric(implementing.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); Assert.True(implementing.ReturnTypeWithAnnotations.Equals(implemented.ReturnTypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } } [Fact] public void Implementing_25() { var source = @" #nullable enable interface I { void M(T value) where T : class; } class C : I { void I.M(T value) { T? x = value; } } "; var compilation = CreateCompilation(source).VerifyDiagnostics(); var c = compilation.GetTypeByMetadataName("C"); var member = c.GetMember("I.M"); var tp = member.GetMemberTypeParameters()[0]; Assert.True(tp.IsReferenceType); Assert.False(tp.IsNullableType()); } [Fact] public void PartialMethods_01() { var source = @" class C { public static void Main() { } } partial class C1 { partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; } partial class C1 { partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class { } }"; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30145: What nullability is getting emitted? compilation.VerifyDiagnostics( // (16,18): warning CS8611: Nullability of reference types in type of parameter 'y' doesn't match partial method declaration. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M1").WithArguments("y").WithLocation(16, 18), // (16,18): warning CS8611: Nullability of reference types in type of parameter 'z' doesn't match partial method declaration. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M1").WithArguments("z").WithLocation(16, 18) ); var c1 = compilation.GetTypeByMetadataName("C1"); var m1 = c1.GetMember("M1"); var m1Impl = m1.PartialImplementationPart; var m1Def = m1.ConstructIfGeneric(m1Impl.TypeParameters.SelectAsArray(t => TypeWithAnnotations.Create(t))); for (int i = 0; i < 3; i++) { Assert.False(m1Impl.Parameters[i].TypeWithAnnotations.Equals(m1Def.Parameters[i].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } Assert.True(m1Impl.Parameters[3].TypeWithAnnotations.Equals(m1Def.Parameters[3].TypeWithAnnotations, TypeCompareKind.AllIgnoreOptions & ~TypeCompareKind.AllNullableIgnoreOptions)); } [Fact] public void PartialMethods_02_01() { var source = @" partial class C1 { #nullable disable partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; } partial class C1 { partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class { } }"; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (10,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 25), // (10,24): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(10, 24), // (10,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 33), // (10,53): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 53), // (10,52): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(10, 52), // (10,74): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 74), // (10,73): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(10, 73), // (10,77): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 77), // (10,79): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 79), // (10,82): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 82), // (5,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 30), // (5,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 29), // (5,72): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 72), // (5,71): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 71), // (5,75): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 75), // (5,77): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 77), // (5,80): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 80) ); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void PartialMethods_02_02() { var source = @" partial class C1 { #nullable disable partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; } #nullable enable partial class C1 { partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class { } }"; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (10,18): warning CS8611: Nullability of reference types in type of parameter 'y' doesn't match partial method declaration. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial, "M1").WithArguments("y").WithLocation(10, 18), // (5,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 30), // (5,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 29), // (5,72): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 72), // (5,71): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 71), // (5,75): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 75), // (5,77): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 77), // (5,80): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 80) ); } [Fact] public void PartialMethods_03() { var source = @" class C { public static void Main() { } } partial class C1 { partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; } partial class C1 { #nullable disable partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class { } }"; var compilation = CreateCompilation(new[] { source }); compilation.VerifyDiagnostics( // (17,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 25), // (17,24): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(17, 24), // (17,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 33), // (17,53): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 53), // (17,52): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(17, 52), // (17,74): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 74), // (17,73): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(17, 73), // (17,77): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 77), // (17,79): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 79), // (17,82): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T? x, T[]? y, System.Action z, System.Action?[]? u) where T : class Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 82), // (11,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 30), // (11,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(11, 29), // (11,72): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 72), // (11,71): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(11, 71), // (11,75): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 75), // (11,77): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 77), // (11,80): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1(T x, T?[] y, System.Action z, System.Action?[]? u) where T : class; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 80) ); } [Fact] public void Overloading_01() { var source = @" class A { void Test1(string? x1) {} void Test1(string x2) {} string Test2(string y1) { return y1; } string? Test2(string y2) { return y2; } } "; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()). VerifyDiagnostics( // (5,10): error CS0111: Type 'A' already defines a member called 'Test1' with the same parameter types // void Test1(string x2) {} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Test1").WithArguments("Test1", "A").WithLocation(5, 10), // (8,13): error CS0111: Type 'A' already defines a member called 'Test2' with the same parameter types // string? Test2(string y2) { return y2; } Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Test2").WithArguments("Test2", "A").WithLocation(8, 13) ); } [Fact] public void Overloading_02() { var source = @" class A { public void M1(T? x) where T : struct { } public void M1(T? x) where T : class { } } "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics(); } [Fact] public void Test1() { CSharpCompilation c = CreateCompilation( new[] { @"#pragma warning disable 8618 class C { static void Main() { } void Test1() { string? x1 = null; string? y1 = x1; string z1 = x1; } void Test2() { string? x2 = """"; string z2 = x2; } void Test3() { string? x3; string z3 = x3; } void Test4() { string x4; string z4 = x4; } void Test5() { string? x5 = """"; x5 = null; string? y5; y5 = x5; string z5; z5 = x5; } void Test6() { string? x6 = """"; string z6; z6 = x6; } void Test7() { CL1? x7 = null; CL1 y7 = x7.P1; CL1 z7 = x7?.P1; x7 = new CL1(); CL1 u7 = x7.P1; } void Test8() { CL1? x8 = new CL1(); CL1 y8 = x8.M1(); x8 = null; CL1 u8 = x8.M1(); CL1 z8 = x8?.M1(); } void Test9(CL1? x9, CL1 y9) { CL1 u9; u9 = x9; u9 = y9; x9 = y9; CL1 v9; v9 = x9; y9 = null; } void Test10(CL1 x10) { CL1 u10; u10 = x10.P1; u10 = x10.P2; u10 = x10.M1(); u10 = x10.M2(); CL1? v10; v10 = x10.P2; v10 = x10.M2(); } void Test11(CL1 x11, CL1? y11) { CL1 u11; u11 = x11.F1; u11 = x11.F2; CL1? v11; v11 = x11.F2; x11.F2 = x11.F1; u11 = x11.F2; v11 = y11.F1; } void Test12(CL1 x12) { S1 y12; CL1 u12; u12 = y12.F3; u12 = y12.F4; } void Test13(CL1 x13) { S1 y13; CL1? u13; u13 = y13.F3; u13 = y13.F4; } void Test14(CL1 x14) { S1 y14; y14.F3 = null; y14.F4 = null; y14.F3 = x14; y14.F4 = x14; } void Test15(CL1 x15) { S1 y15; CL1 u15; y15.F3 = null; y15.F4 = null; u15 = y15.F3; u15 = y15.F4; CL1? v15; v15 = y15.F4; y15.F4 = x15; u15 = y15.F4; } void Test16() { S1 y16; CL1 u16; y16 = new S1(); u16 = y16.F3; u16 = y16.F4; } void Test17(CL1 z17) { S1 x17; x17.F4 = z17; S1 y17 = new S1(); CL1 u17; u17 = y17.F4; y17 = x17; CL1 v17; v17 = y17.F4; } void Test18(CL1 z18) { S1 x18; x18.F4 = z18; S1 y18 = x18; CL1 u18; u18 = y18.F4; } void Test19(S1 x19, CL1 z19) { S1 y19; y19.F4 = null; CL1 u19; u19 = y19.F4; x19.F4 = z19; y19 = x19; CL1 v19; v19 = y19.F4; } void Test20(S1 x20, CL1 z20) { S1 y20; y20.F4 = z20; CL1 u20; u20 = y20.F4; y20 = x20; CL1 v20; v20 = y20.F4; } S1 GetS1() { return new S1(); } void Test21(CL1 z21) { S1 y21; y21.F4 = z21; CL1 u21; u21 = y21.F4; y21 = GetS1(); CL1 v21; v21 = y21.F4; } void Test22() { S1 y22; CL1 u22; u22 = y22.F4; y22 = GetS1(); CL1 v22; v22 = y22.F4; } void Test23(CL1 z23) { S2 y23; y23.F5.F4 = z23; CL1 u23; u23 = y23.F5.F4; y23 = GetS2(); CL1 v23; v23 = y23.F5.F4; } S2 GetS2() { return new S2(); } void Test24() { S2 y24; CL1 u24; u24 = y24.F5.F4; // 1 u24 = y24.F5.F4; // 2 y24 = GetS2(); CL1 v24; v24 = y24.F5.F4; } void Test25(CL1 z25) { S2 y25; S2 x25 = GetS2(); x25.F5.F4 = z25; y25 = x25; CL1 v25; v25 = y25.F5.F4; } void Test26(CL1 x26, CL1? y26, CL1 z26) { x26.P1 = y26; x26.P1 = z26; } void Test27(CL1 x27, CL1? y27, CL1 z27) { x27[x27] = y27; x27[x27] = z27; } void Test28(CL1 x28, CL1? y28, CL1 z28) { x28[y28] = z28; } void Test29(CL1 x29, CL1 y29, CL1 z29) { z29 = x29[y29]; z29 = x29[1]; } void Test30(CL1? x30, CL1 y30, CL1 z30) { z30 = x30[y30]; } void Test31(CL1 x31) { x31 = default(CL1); } void Test32(CL1 x32) { var y32 = new CL1() ?? x32; } void Test33(object x33) { var y33 = new { p = (object)null } ?? x33; } } class CL1 { public CL1() { F1 = this; } public CL1 F1; public CL1? F2; public CL1 P1 { get; set; } public CL1? P2 { get; set; } public CL1 M1() { return new CL1(); } public CL1? M2() { return null; } public CL1 this[CL1 x] { get { return x; } set { } } public CL1? this[int x] { get { return null; } set { } } } struct S1 { public CL1 F3; public CL1? F4; } struct S2 { public S1 F5; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string z1 = x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(12, 21), // (24,21): error CS0165: Use of unassigned local variable 'x3' // string z3 = x3; Diagnostic(ErrorCode.ERR_UseDefViolation, "x3").WithArguments("x3").WithLocation(24, 21), // (30,21): error CS0165: Use of unassigned local variable 'x4' // string z4 = x4; Diagnostic(ErrorCode.ERR_UseDefViolation, "x4").WithArguments("x4").WithLocation(30, 21), // (40,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // z5 = x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(40, 14), // (53,18): warning CS8602: Dereference of a possibly null reference. // CL1 y7 = x7.P1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x7").WithLocation(53, 18), // (54,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z7 = x7?.P1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7?.P1").WithLocation(54, 18), // (64,18): warning CS8602: Dereference of a possibly null reference. // CL1 u8 = x8.M1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x8").WithLocation(64, 18), // (65,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z8 = x8?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x8?.M1()").WithLocation(65, 18), // (71,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // u9 = x9; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x9").WithLocation(71, 14), // (76,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y9 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(76, 14), // (83,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u10 = x10.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x10.P2").WithLocation(83, 15), // (85,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u10 = x10.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x10.M2()").WithLocation(85, 15), // (95,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u11 = x11.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11.F2").WithLocation(95, 15), // (101,15): warning CS8602: Dereference of a possibly null reference. // v11 = y11.F1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y11").WithLocation(101, 15), // (108,15): error CS0170: Use of possibly unassigned field 'F3' // u12 = y12.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y12.F3").WithArguments("F3").WithLocation(108, 15), // (109,15): error CS0170: Use of possibly unassigned field 'F4' // u12 = y12.F4; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y12.F4").WithArguments("F4").WithLocation(109, 15), // (109,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u12 = y12.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y12.F4").WithLocation(109, 15), // (116,15): error CS0170: Use of possibly unassigned field 'F3' // u13 = y13.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y13.F3").WithArguments("F3").WithLocation(116, 15), // (117,15): error CS0170: Use of possibly unassigned field 'F4' // u13 = y13.F4; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y13.F4").WithArguments("F4").WithLocation(117, 15), // (123,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // y14.F3 = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(123, 18), // (133,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // y15.F3 = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(133, 18), // (135,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u15 = y15.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y15.F3").WithLocation(135, 15), // (136,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u15 = y15.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y15.F4").WithLocation(136, 15), // (149,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u16 = y16.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y16.F3").WithLocation(149, 15), // (150,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u16 = y16.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y16.F4").WithLocation(150, 15), // (161,15): error CS0165: Use of unassigned local variable 'x17' // y17 = x17; Diagnostic(ErrorCode.ERR_UseDefViolation, "x17").WithArguments("x17").WithLocation(161, 15), // (159,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u17 = y17.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y17.F4").WithLocation(159, 15), // (170,18): error CS0165: Use of unassigned local variable 'x18' // S1 y18 = x18; Diagnostic(ErrorCode.ERR_UseDefViolation, "x18").WithArguments("x18").WithLocation(170, 18), // (180,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u19 = y19.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y19.F4").WithLocation(180, 15), // (197,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v20 = y20.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y20.F4").WithLocation(197, 15), // (213,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v21 = y21.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y21.F4").WithLocation(213, 15), // (220,15): error CS0170: Use of possibly unassigned field 'F4' // u22 = y22.F4; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y22.F4").WithArguments("F4").WithLocation(220, 15), // (220,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u22 = y22.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y22.F4").WithLocation(220, 15), // (224,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v22 = y22.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y22.F4").WithLocation(224, 15), // (236,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v23 = y23.F5.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y23.F5.F4").WithLocation(236, 15), // (248,15): error CS0170: Use of possibly unassigned field 'F4' // u24 = y24.F5.F4; // 1 Diagnostic(ErrorCode.ERR_UseDefViolationField, "y24.F5.F4").WithArguments("F4").WithLocation(248, 15), // (248,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u24 = y24.F5.F4; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y24.F5.F4").WithLocation(248, 15), // (249,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // u24 = y24.F5.F4; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y24.F5.F4").WithLocation(249, 15), // (253,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // v24 = y24.F5.F4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y24.F5.F4").WithLocation(253, 15), // (268,18): warning CS8601: Possible null reference assignment. // x26.P1 = y26; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y26").WithLocation(268, 18), // (274,20): warning CS8601: Possible null reference assignment. // x27[x27] = y27; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y27").WithLocation(274, 20), // (280,13): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL1.this[CL1 x]'. // x28[y28] = z28; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y28").WithArguments("x", "CL1 CL1.this[CL1 x]").WithLocation(280, 13), // (286,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // z29 = x29[1]; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x29[1]").WithLocation(286, 15), // (291,15): warning CS8602: Dereference of a possibly null reference. // z30 = x30[y30]; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x30").WithLocation(291, 15), // (296,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // x31 = default(CL1); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(CL1)").WithLocation(296, 15), // (306,29): warning CS8600: Converting null literal or possible null value to non-nullable type. // var y33 = new { p = (object)null } ?? x33; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)null").WithLocation(306, 29) ); } [Fact] public void PassingParameters_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void M1(CL1 p) {} void Test1(CL1? x1, CL1 y1) { M1(x1); M1(y1); } void Test2() { CL1? x2; M1(x2); } void M2(ref CL1? p) {} void Test3() { CL1 x3; M2(ref x3); } void Test4(CL1 x4) { M2(ref x4); } void M3(out CL1? p) { p = null; } void Test5() { CL1 x5; M3(out x5); } void M4(ref CL1 p) {} void Test6() { CL1? x6 = null; M4(ref x6); } void M5(out CL1 p) { p = new CL1(); } void Test7() { CL1? x7 = null; CL1 u7 = x7; M5(out x7); CL1 v7 = x7; } void M6(CL1 p1, CL1? p2) {} void Test8(CL1? x8, CL1? y8) { M6(p2: x8, p1: y8); } void M7(params CL1[] p1) {} void Test9(CL1 x9, CL1? y9) { M7(x9, y9); } void Test10(CL1? x10, CL1 y10) { M7(x10, y10); } void M8(CL1 p1, params CL1[] p2) {} void Test11(CL1? x11, CL1 y11, CL1? z11) { M8(x11, y11, z11); } void Test12(CL1? x12, CL1 y12) { M8(p2: x12, p1: y12); } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,12): warning CS8604: Possible null reference argument for parameter 'p' in 'void C.M1(CL1 p)'. // M1(x1); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("p", "void C.M1(CL1 p)").WithLocation(12, 12), // (19,12): error CS0165: Use of unassigned local variable 'x2' // M1(x2); Diagnostic(ErrorCode.ERR_UseDefViolation, "x2").WithArguments("x2").WithLocation(19, 12), // (27,16): error CS0165: Use of unassigned local variable 'x3' // M2(ref x3); Diagnostic(ErrorCode.ERR_UseDefViolation, "x3").WithArguments("x3").WithLocation(27, 16), // (27,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // M2(ref x3); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(27, 16), // (32,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // M2(ref x4); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x4").WithLocation(32, 16), // (40,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // M3(out x5); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(40, 16), // (48,16): warning CS8601: Possible null reference assignment. // M4(ref x6); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x6").WithLocation(48, 16), // (56,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u7 = x7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7").WithLocation(56, 18), // (65,24): warning CS8604: Possible null reference argument for parameter 'p1' in 'void C.M6(CL1 p1, CL1? p2)'. // M6(p2: x8, p1: y8); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y8").WithArguments("p1", "void C.M6(CL1 p1, CL1? p2)").WithLocation(65, 24), // (72,16): warning CS8604: Possible null reference argument for parameter 'p1' in 'void C.M7(params CL1[] p1)'. // M7(x9, y9); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y9").WithArguments("p1", "void C.M7(params CL1[] p1)").WithLocation(72, 16), // (77,12): warning CS8604: Possible null reference argument for parameter 'p1' in 'void C.M7(params CL1[] p1)'. // M7(x10, y10); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x10").WithArguments("p1", "void C.M7(params CL1[] p1)").WithLocation(77, 12), // (84,12): warning CS8604: Possible null reference argument for parameter 'p1' in 'void C.M8(CL1 p1, params CL1[] p2)'. // M8(x11, y11, z11); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x11").WithArguments("p1", "void C.M8(CL1 p1, params CL1[] p2)").WithLocation(84, 12), // (84,22): warning CS8604: Possible null reference argument for parameter 'p2' in 'void C.M8(CL1 p1, params CL1[] p2)'. // M8(x11, y11, z11); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "z11").WithArguments("p2", "void C.M8(CL1 p1, params CL1[] p2)").WithLocation(84, 22), // (89,16): warning CS8604: Possible null reference argument for parameter 'p2' in 'void C.M8(CL1 p1, params CL1[] p2)'. // M8(p2: x12, p1: y12); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x12").WithArguments("p2", "void C.M8(CL1 p1, params CL1[] p2)").WithLocation(89, 16) ); } [Fact] public void PassingParameters_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1) { var y1 = new CL0() { [null] = x1 }; } } class CL0 { public CL0 this[CL0 x] { get { return x; } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // var y1 = new CL0() { [null] = x1 }; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 31)); } [Fact] public void PassingParameters_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1) { var y1 = new CL0() { null }; } } class CL0 : System.Collections.IEnumerable { public void Add(CL0 x) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,30): warning CS8625: Cannot convert null literal to non-nullable reference type. // var y1 = new CL0() { null }; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 30)); } [Fact] public void PassingParameters_04() { var source = @"interface I { } class C { static void F(I x, I y, I? z, I? w, I[]? a) { G(x); G(y); G(x, x, x); G(x, y, y); G(x, x, y, z, w); G(y: x, x: y); G(y: y, x: x); G(x, a); G(x, new I[0]); G(x, new[] { x, x }); G(x, new[] { y, y }); G(x, new[] { x, y, z }); G(y: new[] { x, x }, x: y); G(y: new[] { y, y }, x: x); } static void G(I x, params I[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.G(I x, params I[] y)'. // G(y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "x", "void C.G(I x, params I[] y)").WithLocation(7, 11), // (8,14): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, x, x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "y", "void C.G(I x, params I[] y)").WithLocation(8, 14), // (8,17): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, x, x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "y", "void C.G(I x, params I[] y)").WithLocation(8, 17), // (10,14): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, x, y, z, w); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "y", "void C.G(I x, params I[] y)").WithLocation(10, 14), // (10,20): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, x, y, z, w); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "z").WithArguments("y", "void C.G(I x, params I[] y)").WithLocation(10, 20), // (10,20): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, x, y, z, w); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("I", "I", "y", "void C.G(I x, params I[] y)").WithLocation(10, 20), // (10,23): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, x, y, z, w); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "w").WithArguments("y", "void C.G(I x, params I[] y)").WithLocation(10, 23), // (11,14): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(y: x, x: y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "y", "void C.G(I x, params I[] y)").WithLocation(11, 14), // (11,20): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.G(I x, params I[] y)'. // G(y: x, x: y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "x", "void C.G(I x, params I[] y)").WithLocation(11, 20), // (13,14): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, a); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a").WithArguments("y", "void C.G(I x, params I[] y)").WithLocation(13, 14), // (15,14): warning CS8620: Nullability of reference types in argument of type 'I[]' doesn't match target type 'I[]' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, new[] { x, x }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new[] { x, x }").WithArguments("I[]", "I[]", "y", "void C.G(I x, params I[] y)").WithLocation(15, 14), // (17,14): warning CS8620: Nullability of reference types in argument of type 'I?[]' doesn't match target type 'I[]' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(x, new[] { x, y, z }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new[] { x, y, z }").WithArguments("I?[]", "I[]", "y", "void C.G(I x, params I[] y)").WithLocation(17, 14), // (17,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // G(x, new[] { x, y, z }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(17, 25), // (18,14): warning CS8620: Nullability of reference types in argument of type 'I[]' doesn't match target type 'I[]' for parameter 'y' in 'void C.G(I x, params I[] y)'. // G(y: new[] { x, x }, x: y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new[] { x, x }").WithArguments("I[]", "I[]", "y", "void C.G(I x, params I[] y)").WithLocation(18, 14), // (18,33): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.G(I x, params I[] y)'. // G(y: new[] { x, x }, x: y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "x", "void C.G(I x, params I[] y)").WithLocation(18, 33) ); } [Fact] public void PassingParameters_DifferentRefKinds() { var source = @" class C { void M(string xNone, ref string xRef, out string xOut) { xNone = null; xRef = null; xOut = null; } } "; var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // xNone = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 17), // (7,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // xRef = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 16), // (8,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // xOut = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 16) ); var source2 = @" class C { void M(in string xIn) { xIn = null; } } "; var c2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue()); c2.VerifyDiagnostics( // (6,9): error CS8331: Cannot assign to variable 'in string' because it is a readonly variable // xIn = null; Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "xIn").WithArguments("variable", "in string").WithLocation(6, 9)); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void PassingParameters_UnknownMethod() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static int F(object x) { Missing(F(null)); // 1 Missing(F(x = null)); // 2 x.ToString(); // 3 Missing(F(x = this)); // 4 x.ToString(); return 0; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,9): error CS0103: The name 'Missing' does not exist in the current context // Missing(F(null)); // 1 Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(6, 9), // (6,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // Missing(F(null)); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 19), // (7,9): error CS0103: The name 'Missing' does not exist in the current context // Missing(F(x = null)); // 2 Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(7, 9), // (7,19): warning CS8604: Possible null reference argument for parameter 'x' in 'int C.F(object x)'. // Missing(F(x = null)); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x = null").WithArguments("x", "int C.F(object x)").WithLocation(7, 19), // (7,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Missing(F(x = null)); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 9), // (10,9): error CS0103: The name 'Missing' does not exist in the current context // Missing(F(x = this)); // 4 Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(10, 9), // (10,23): error CS0026: Keyword 'this' is not valid in a static property, static method, or static field initializer // Missing(F(x = this)); // 4 Diagnostic(ErrorCode.ERR_ThisInStaticMeth, "this").WithLocation(10, 23) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void PassingParameters_UnknownMethod_UnknownReceiver() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static int F(object x) { bad.Missing(F(null)); // 1 bad.Missing(F(x = null)); // 2 x.ToString(); // 3 bad.Missing(F(x = this)); // 4 x.ToString(); return 0; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,9): error CS0103: The name 'bad' does not exist in the current context // bad.Missing(F(null)); // 1 Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(6, 9), // (6,23): warning CS8625: Cannot convert null literal to non-nullable reference type. // bad.Missing(F(null)); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 23), // (7,9): error CS0103: The name 'bad' does not exist in the current context // bad.Missing(F(x = null)); // 2 Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(7, 9), // (7,23): warning CS8604: Possible null reference argument for parameter 'x' in 'int C.F(object x)'. // bad.Missing(F(x = null)); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x = null").WithArguments("x", "int C.F(object x)").WithLocation(7, 23), // (7,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // bad.Missing(F(x = null)); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 27), // (8,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 9), // (10,9): error CS0103: The name 'bad' does not exist in the current context // bad.Missing(F(x = this)); // 4 Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(10, 9), // (10,27): error CS0026: Keyword 'this' is not valid in a static property, static method, or static field initializer // bad.Missing(F(x = this)); // 4 Diagnostic(ErrorCode.ERR_ThisInStaticMeth, "this").WithLocation(10, 27) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void PassingParameters_UnknownMethod_AffectingState() { CSharpCompilation c = CreateCompilation(new[] { @" class C { object F(object x) { Missing( F(x = null) /*warn*/, x.ToString() /*warn*/, F(x = this), x.ToString()); return x; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,9): error CS0103: The name 'Missing' does not exist in the current context // Missing( Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(6, 9), // (7,15): warning CS8604: Possible null reference argument for parameter 'x' in 'object C.F(object x)'. // F(x = null) /*warn*/, Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x = null").WithArguments("x", "object C.F(object x)").WithLocation(7, 15), // (7,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(x = null) /*warn*/, Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 19), // (8,13): warning CS8602: Dereference of a possibly null reference. // x.ToString() /*warn*/, Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void PassingParameters_UnknownMethod_AffectingConditionalState() { CSharpCompilation c = CreateCompilation(new[] { @" class C { int F(object x) { if (G(F(x = null))) { x.ToString(); // 1 } else { x.ToString(); // 2 } return 0; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,13): error CS0103: The name 'G' does not exist in the current context // if (G(F(x = null))) Diagnostic(ErrorCode.ERR_NameNotInContext, "G").WithArguments("G").WithLocation(6, 13), // (6,17): warning CS8604: Possible null reference argument for parameter 'x' in 'int C.F(object x)'. // if (G(F(x = null))) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x = null").WithArguments("x", "int C.F(object x)").WithLocation(6, 17), // (6,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // if (G(F(x = null))) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 21), // (8,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(12, 13) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void PassingParameters_UnknownMethod_AffectingConditionalState2() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void F(object x) { if (Missing(x) && Missing(x = null)) { x.ToString(); // 1 } else { x.ToString(); // 2 } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,13): error CS0103: The name 'Missing' does not exist in the current context // if (Missing(x) && Missing(x = null)) Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(6, 13), // (6,27): error CS0103: The name 'Missing' does not exist in the current context // if (Missing(x) && Missing(x = null)) Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(6, 27), // (6,39): warning CS8600: Converting null literal or possible null value to non-nullable type. // if (Missing(x) && Missing(x = null)) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 39), // (8,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(12, 13) ); } [Fact] public void DuplicateArguments() { var source = @"class C { static void F(object x, object? y) { // Duplicate x G(x: x, x: y); G(x: y, x: x); G(x: x, x: y, y: y); G(x: y, x: x, y: y); G(y: y, x: x, x: y); G(y: y, x: y, x: x); // Duplicate y G(y: x, y: y); G(y: y, y: x); G(x, y: x, y: y); G(x, y: y, y: x); G(y: x, y: y, x: x); G(y: y, y: x, x: x); } static void G(object x, params object?[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,17): error CS1740: Named argument 'x' cannot be specified multiple times // G(x: x, x: y); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "x").WithArguments("x").WithLocation(6, 17), // (7,17): error CS1740: Named argument 'x' cannot be specified multiple times // G(x: y, x: x); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "x").WithArguments("x").WithLocation(7, 17), // (8,17): error CS1740: Named argument 'x' cannot be specified multiple times // G(x: x, x: y, y: y); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "x").WithArguments("x").WithLocation(8, 17), // (9,17): error CS1740: Named argument 'x' cannot be specified multiple times // G(x: y, x: x, y: y); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "x").WithArguments("x").WithLocation(9, 17), // (10,23): error CS1740: Named argument 'x' cannot be specified multiple times // G(y: y, x: x, x: y); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "x").WithArguments("x").WithLocation(10, 23), // (11,23): error CS1740: Named argument 'x' cannot be specified multiple times // G(y: y, x: y, x: x); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "x").WithArguments("x").WithLocation(11, 23), // (13,9): error CS7036: There is no argument given that corresponds to the required formal parameter 'x' of 'C.G(object, params object?[])' // G(y: x, y: y); Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "G").WithArguments("x", "C.G(object, params object?[])").WithLocation(13, 9), // (14,9): error CS7036: There is no argument given that corresponds to the required formal parameter 'x' of 'C.G(object, params object?[])' // G(y: y, y: x); Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "G").WithArguments("x", "C.G(object, params object?[])").WithLocation(14, 9), // (15,20): error CS1740: Named argument 'y' cannot be specified multiple times // G(x, y: x, y: y); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "y").WithArguments("y").WithLocation(15, 20), // (16,20): error CS1740: Named argument 'y' cannot be specified multiple times // G(x, y: y, y: x); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "y").WithArguments("y").WithLocation(16, 20), // (17,17): error CS1740: Named argument 'y' cannot be specified multiple times // G(y: x, y: y, x: x); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "y").WithArguments("y").WithLocation(17, 17), // (18,17): error CS1740: Named argument 'y' cannot be specified multiple times // G(y: y, y: x, x: x); Diagnostic(ErrorCode.ERR_DuplicateNamedArgument, "y").WithArguments("y").WithLocation(18, 17)); } [Fact] public void MissingArguments() { var source = @"class C { static void F(object? x) { G(y: x); } static void G(object? x = null, object y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,45): error CS1737: Optional parameters must appear after all required parameters // static void G(object? x = null, object y) Diagnostic(ErrorCode.ERR_DefaultValueBeforeRequiredValue, ")").WithLocation(7, 45), // (5,14): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.G(object? x = null, object y)'. // G(y: x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("y", "void C.G(object? x = null, object y)").WithLocation(5, 14)); } [Fact] public void ParamsArgument_NotLast() { var source = @"class C { static void F(object[]? a, object? b) { G(a, b, a); } static void G(params object[] x, params object[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,19): error CS0231: A params parameter must be the last parameter in a formal parameter list // static void G(params object[] x, params object[] y) Diagnostic(ErrorCode.ERR_ParamsLast, "params object[] x").WithLocation(7, 19), // (5,11): warning CS8604: Possible null reference argument for parameter 'x' in 'void C.G(params object[] x, params object[] y)'. // G(a, b, a); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a").WithArguments("x", "void C.G(params object[] x, params object[] y)").WithLocation(5, 11), // (5,14): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.G(params object[] x, params object[] y)'. // G(a, b, a); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("y", "void C.G(params object[] x, params object[] y)").WithLocation(5, 14), // (5,17): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.G(params object[] x, params object[] y)'. // G(a, b, a); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a").WithArguments("y", "void C.G(params object[] x, params object[] y)").WithLocation(5, 17)); } [Fact] public void ParamsArgument_NotArray() { var source = @"class C { static void F1(object x, object? y) { F2(y); F2(x, y); F3(y, x); F3(x, y, x); } static void F2(params object x) { } static void F3(params object x, params object[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,20): error CS0225: The params parameter must be a single dimensional array // static void F2(params object x) Diagnostic(ErrorCode.ERR_ParamsMustBeArray, "params").WithLocation(10, 20), // (13,20): error CS0225: The params parameter must be a single dimensional array // static void F3(params object x, params object[] y) Diagnostic(ErrorCode.ERR_ParamsMustBeArray, "params").WithLocation(13, 20), // (13,20): error CS0231: A params parameter must be the last parameter in a formal parameter list // static void F3(params object x, params object[] y) Diagnostic(ErrorCode.ERR_ParamsLast, "params object x").WithLocation(13, 20), // (6,9): error CS1501: No overload for method 'F2' takes 2 arguments // F2(x, y); Diagnostic(ErrorCode.ERR_BadArgCount, "F2").WithArguments("F2", "2").WithLocation(6, 9), // (5,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void C.F2(params object x)'. // F2(y); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void C.F2(params object x)").WithLocation(5, 12), // (7,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void C.F3(params object x, params object[] y)'. // F3(y, x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void C.F3(params object x, params object[] y)").WithLocation(7, 12), // (8,15): warning CS8604: Possible null reference argument for parameter 'y' in 'void C.F3(params object x, params object[] y)'. // F3(x, y, x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("y", "void C.F3(params object x, params object[] y)").WithLocation(8, 15)); } [Fact] public void ParamsArgument_BinaryOperator() { var source = @"class C { public static object operator+(C x, params object?[] y) => x; static object F(C x, object[] y) => x + y; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,41): error CS1670: params is not valid in this context // public static object operator+(C x, params object?[] y) => x; Diagnostic(ErrorCode.ERR_IllegalParams, "params").WithLocation(3, 41), // (4,45): warning CS8620: Nullability of reference types in argument of type 'object[]' doesn't match target type 'object?[]' for parameter 'y' in 'object C.operator +(C x, params object?[] y)'. // static object F(C x, object[] y) => x + y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("object[]", "object?[]", "y", "object C.operator +(C x, params object?[] y)").WithLocation(4, 45)); } [Fact] public void RefOutParameters_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(ref CL1 x1, CL1 y1) { y1 = x1; } void Test2(ref CL1? x2, CL1 y2) { y2 = x2; } void Test3(ref CL1? x3, CL1 y3) { x3 = y3; y3 = x3; } void Test4(out CL1 x4, CL1 y4) { y4 = x4; x4 = y4; } void Test5(out CL1? x5, CL1 y5) { y5 = x5; x5 = y5; } void Test6(out CL1? x6, CL1 y6) { x6 = y6; y6 = x6; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(15, 14), // (26,14): error CS0269: Use of unassigned out parameter 'x4' // y4 = x4; Diagnostic(ErrorCode.ERR_UseDefViolationOut, "x4").WithArguments("x4").WithLocation(26, 14), // (32,14): error CS0269: Use of unassigned out parameter 'x5' // y5 = x5; Diagnostic(ErrorCode.ERR_UseDefViolationOut, "x5").WithArguments("x5").WithLocation(32, 14) ); } [Fact] public void RefOutParameters_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(ref S1 x1, CL1 y1) { y1 = x1.F1; } void Test2(ref S1 x2, CL1 y2) { y2 = x2.F2; } void Test3(ref S1 x3, CL1 y3) { x3.F2 = y3; y3 = x3.F2; } void Test4(out S1 x4, CL1 y4) { y4 = x4.F1; x4.F1 = y4; x4.F2 = y4; } void Test5(out S1 x5, CL1 y5) { y5 = x5.F2; x5.F1 = y5; x5.F2 = y5; } void Test6(out S1 x6, CL1 y6) { x6.F1 = y6; x6.F2 = y6; y6 = x6.F2; } } class CL1 { } struct S1 { public CL1 F1; public CL1? F2; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = x2.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2.F2").WithLocation(15, 14), // (26,14): error CS0170: Use of possibly unassigned field 'F1' // y4 = x4.F1; Diagnostic(ErrorCode.ERR_UseDefViolationField, "x4.F1").WithArguments("F1").WithLocation(26, 14), // (33,14): error CS0170: Use of possibly unassigned field 'F2' // y5 = x5.F2; Diagnostic(ErrorCode.ERR_UseDefViolationField, "x5.F2").WithArguments("F2").WithLocation(33, 14), // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y5 = x5.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5.F2").WithLocation(33, 14), // (34,17): warning CS8601: Possible null reference assignment. // x5.F1 = y5; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y5").WithLocation(34, 17)); } [Fact] public void RefOutParameters_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test3(ref S1 x3, CL1 y3) { S1 z3; z3.F1 = y3; z3.F2 = y3; x3 = z3; y3 = x3.F2; } void Test6(out S1 x6, CL1 y6) { S1 z6; z6.F1 = y6; z6.F2 = y6; x6 = z6; y6 = x6.F2; } } class CL1 { } struct S1 { public CL1 F1; public CL1? F2; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void RefOutParameters_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void M1(ref CL0 x) {} void Test1(CL0 x1) { M1(ref x1); } void M2(out CL0 x) { throw new System.NotImplementedException(); } void Test2(CL0 x2) { M2(out x2); } void M3(CL0 x) {} void Test3(CL0 x3) { M3(x3); } } class CL0 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,16): warning CS8620: Argument of type 'CL0' cannot be used as an input of type 'CL0' for parameter 'x' in 'void C.M1(ref CL0 x)' due to differences in the nullability of reference types. // M1(ref x1); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("CL0", "CL0", "x", "void C.M1(ref CL0 x)").WithLocation(12, 16), // (19,16): warning CS8624: Argument of type 'CL0' cannot be used as an output of type 'CL0' for parameter 'x' in 'void C.M2(out CL0 x)' due to differences in the nullability of reference types. // M2(out x2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x2").WithArguments("CL0", "CL0", "x", "void C.M2(out CL0 x)").WithLocation(19, 16), // (26,12): warning CS8620: Argument of type 'CL0' cannot be used as an input of type 'CL0' for parameter 'x' in 'void C.M3(CL0 x)' due to differences in the nullability of reference types. // M3(x3); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x3").WithArguments("CL0", "CL0", "x", "void C.M3(CL0 x)").WithLocation(26, 12)); } [Fact] public void RefOutParameters_05() { var source = @"class C { static void F(object? x, object? y, object? z) { G(out x, ref y, in z); x.ToString(); y.ToString(); z.ToString(); } static void G(out object x, ref object y, in object z) { x = new object(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,22): warning CS8601: Possible null reference assignment. // G(out x, ref y, in z); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(5, 22), // (5,28): warning CS8604: Possible null reference argument for parameter 'z' in 'void C.G(out object x, ref object y, in object z)'. // G(out x, ref y, in z); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "z").WithArguments("z", "void C.G(out object x, ref object y, in object z)").WithLocation(5, 28), // (8,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(8, 9) ); } [Fact] public void RefOutParameters_06() { var source = @"class C { static void F(object x, object y, object z) { G(out x, ref y, in z); x.ToString(); y.ToString(); z.ToString(); } static void G(out object? x, ref object? y, in object? z) { x = new object(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // G(out x, ref y, in z); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(5, 15), // (5,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // G(out x, ref y, in z); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(5, 22), // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(7, 9)); } [Fact] public void TargetingUnannotatedAPIs_01() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public object F1; public object P1 { get; set;} public object this[object x] { get { return null; } set { } } public S1 M1() { return new S1(); } } public struct S1 { public CL0 F1; } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } bool Test1(string? x1, string y1) { return string.Equals(x1, y1); } object Test2(ref object? x2, object? y2) { System.Threading.Interlocked.Exchange(ref x2, y2); return x2 ?? new object(); } object Test3(ref object? x3, object? y3) { return System.Threading.Interlocked.Exchange(ref x3, y3) ?? new object(); } object Test4(System.Delegate x4) { return x4.Target ?? new object(); } object Test5(CL0 x5) { return x5.F1 ?? new object(); } void Test6(CL0 x6, object? y6) { x6.F1 = y6; } void Test7(CL0 x7, object? y7) { x7.P1 = y7; } void Test8(CL0 x8, object? y8, object? z8) { x8[y8] = z8; } object Test9(CL0 x9) { return x9[1] ?? new object(); } object Test10(CL0 x10) { return x10.M1().F1 ?? new object(); } object Test11(CL0 x11, CL0? z11) { S1 y11 = x11.M1(); y11.F1 = z11; return y11.F1; } object Test12(CL0 x12) { S1 y12 = x12.M1(); y12.F1 = x12; return y12.F1 ?? new object(); } void Test13(CL0 x13, object? y13) { y13 = x13.F1; object z13 = y13; z13 = y13 ?? new object(); } void Test14(CL0 x14) { object? y14 = x14.F1; object z14 = y14; z14 = y14 ?? new object(); } void Test15(CL0 x15) { S2 y15; y15.F2 = x15.F1; object z15 = y15.F2; z15 = y15.F2 ?? new object(); } struct Test16 { object? y16 {get;} public Test16(CL0 x16) { y16 = x16.F1; object z16 = y16; z16 = y16 ?? new object(); } } void Test17(CL0 x17) { var y17 = new { F2 = x17.F1 }; object z17 = y17.F2; z17 = y17.F2 ?? new object(); } } public struct S2 { public object? F2; } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( // (63,16): warning CS8603: Possible null reference return. // return y11.F1; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y11.F1").WithLocation(63, 16)); } [Fact] public void TargetingUnannotatedAPIs_02() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public static object M1() { return new object(); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } public static object? M2() { return null; } public static object M3() { return new object(); } void Test1() { object? x1 = CL0.M1() ?? M2(); object y1 = x1; object z1 = x1 ?? new object(); } void Test2() { object? x2 = CL0.M1() ?? M3(); object z2 = x2 ?? new object(); } void Test3() { object? x3 = M3() ?? M2(); object z3 = x3 ?? new object(); } void Test4() { object? x4 = CL0.M1() ?? CL0.M1(); object y4 = x4; object z4 = x4 ?? new object(); } void Test5() { object x5 = M2() ?? M2(); } void Test6() { object? x6 = M3() ?? M3(); object z6 = x6 ?? new object(); } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( // (14,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y1 = x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(14, 21), // (39,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x5 = M2() ?? M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M2() ?? M2()").WithLocation(39, 21)); } [Fact] public void TargetingUnannotatedAPIs_03() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public static object M1() { return new object(); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } public static object? M2() { return null; } public static object M3() { return new object(); } void Test1() { object? x1 = M2() ?? CL0.M1(); object y1 = x1; object z1 = x1 ?? new object(); } void Test2() { object? x2 = M3() ?? CL0.M1(); object z2 = x2 ?? new object(); } void Test3() { object? x3 = M2() ?? M3(); object z3 = x3 ?? new object(); } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( ); } [Fact] public void TargetingUnannotatedAPIs_04() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public static object M1() { return new object(); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } public static object? M2() { return null; } public static object M3() { return new object(); } public static bool M4() {return false;} void Test1() { object x1 = M4() ? CL0.M1() : M2(); } void Test2() { object? x2 = M4() ? CL0.M1() : M3(); object y2 = x2; object z2 = x2 ?? new object(); } void Test3() { object x3 = M4() ? M3() : M2(); } void Test4() { object? x4 = M4() ? CL0.M1() : CL0.M1(); object y4 = x4; object z4 = x4 ?? new object(); } void Test5() { object x5 = M4() ? M2() : M2(); } void Test6() { object? x6 = M4() ? M3() : M3(); object z6 = x6 ?? new object(); } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( // (14,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x1 = M4() ? CL0.M1() : M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? CL0.M1() : M2()").WithLocation(14, 21), // (26,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x3 = M4() ? M3() : M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M3() : M2()").WithLocation(26, 22), // (38,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x5 = M4() ? M2() : M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M2() : M2()").WithLocation(38, 22) ); } [Fact] public void TargetingUnannotatedAPIs_05() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public static object M1() { return new object(); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } public static object? M2() { return null; } public static object M3() { return new object(); } public static bool M4() {return false;} void Test1() { object x1 = M4() ? M2() : CL0.M1(); } void Test2() { object? x2 = M4() ? M3() : CL0.M1(); object y2 = x2; object z2 = x2 ?? new object(); } void Test3() { object x3 = M4() ? M2() : M3(); } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( // (14,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x1 = M4() ? M2() : CL0.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M2() : CL0.M1()").WithLocation(14, 21), // (26,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x3 = M4() ? M2() : M3(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M4() ? M2() : M3()").WithLocation(26, 22) ); } [Fact] public void TargetingUnannotatedAPIs_06() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public static object M1() { return new object(); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } public static object? M2() { return null; } public static object M3() { return new object(); } public static bool M4() {return false;} void Test1() { object? x1; if (M4()) x1 = CL0.M1(); else x1 = M2(); object y1 = x1; } void Test2() { object? x2; if (M4()) x2 = CL0.M1(); else x2 = M3(); object y2 = x2; object z2 = x2 ?? new object(); } void Test3() { object? x3; if (M4()) x3 = M3(); else x3 = M2(); object y3 = x3; } void Test4() { object? x4; if (M4()) x4 = CL0.M1(); else x4 = CL0.M1(); object y4 = x4; object z4 = x4 ?? new object(); } void Test5() { object? x5; if (M4()) x5 = M2(); else x5 = M2(); object y5 = x5; } void Test6() { object? x6; if (M4()) x6 = M3(); else x6 = M3(); object z6 = x6 ?? new object(); } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( // (16,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y1 = x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(16, 21), // (31,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(31, 21), // (46,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y5 = x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(46, 21) ); } [Fact] public void TargetingUnannotatedAPIs_07() { CSharpCompilation c0 = CreateCompilation(@" public class CL0 { public static object M1() { return new object(); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } public static object? M2() { return null; } public static object M3() { return new object(); } public static bool M4() {return false;} void Test1() { object? x1; if (M4()) x1 = M2(); else x1 = CL0.M1(); object y1 = x1; } void Test2() { object? x2; if (M4()) x2 = M3(); else x2 = CL0.M1(); object y2 = x2; object z2 = x2 ?? new object(); } void Test3() { object? x3; if (M4()) x3 = M2(); else x3 = M3(); object y3 = x3; } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics( // (16,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y1 = x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(16, 21), // (31,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(31, 21) ); } [Fact] public void TargetingUnannotatedAPIs_08() { CSharpCompilation c0 = CreateCompilation(@" public abstract class A1 { public abstract event System.Action E1; public abstract string P2 { get; set; } public abstract string M3(string x); public abstract event System.Action E4; public abstract string this[string x] { get; set; } } public interface IA2 { event System.Action E5; string P6 { get; set; } string M7(string x); event System.Action E8; string this[string x] { get; set; } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class B1 : A1 { static void Main() { } public override string? P2 { get; set; } public override event System.Action? E1; public override string? M3(string? x) { var dummy = E1; throw new System.NotImplementedException(); } public override event System.Action? E4 { add { } remove { } } public override string? this[string? x] { get { throw new System.NotImplementedException(); } set { throw new System.NotImplementedException(); } } } class B2 : IA2 { public string? P6 { get; set; } public event System.Action? E5; public event System.Action? E8 { add { } remove { } } public string? M7(string? x) { var dummy = E5; throw new System.NotImplementedException(); } public string? this[string? x] { get { throw new System.NotImplementedException(); } set { throw new System.NotImplementedException(); } } } class B3 : IA2 { string? IA2.P6 { get; set; } event System.Action? IA2.E5 { add { } remove { } } event System.Action? IA2.E8 { add { } remove { } } string? IA2.M7(string? x) { throw new System.NotImplementedException(); } string? IA2.this[string? x] { get { throw new System.NotImplementedException(); } set { throw new System.NotImplementedException(); } } } " }, options: WithNonNullTypesTrue(), references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics(); } [Fact] public void ReturningValues_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1 Test1(CL1? x1) { return x1; } CL1? Test2(CL1? x2) { return x2; } CL1? Test3(CL1 x3) { return x3; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,16): warning CS8603: Possible null reference return. // return x1; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "x1").WithLocation(10, 16) ); } [Fact] public void ReturningValues_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1 Test1(CL1 x1) { return x1; } CL1 Test2(CL1 x2) { return x2; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,16): warning CS8619: Nullability of reference types in value of type 'CL1' doesn't match target type 'CL1'. // return x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("CL1", "CL1").WithLocation(10, 16), // (15,16): warning CS8619: Nullability of reference types in value of type 'CL1' doesn't match target type 'CL1'. // return x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("CL1", "CL1").WithLocation(15, 16) ); } [Fact] public void ReturningValues_BadValue() { CSharpCompilation c = CreateCompilation(new[] { @" class C { string M() { return bad; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,16): error CS0103: The name 'bad' does not exist in the current context // return bad; Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(6, 16) ); } [Fact] public void IdentityConversion_Return_01() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static I F(I x) => x; static IIn F(IIn x) => x; static IOut F(IOut x) => x; static I G(I x) => x; static IIn G(IIn x) => x; static IOut G(IOut x) => x; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,41): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static I F(I x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(6, 41), // (7,45): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // static IIn F(IIn x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(7, 45), // (9,41): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static I G(I x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(9, 41), // (11,47): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // static IOut G(IOut x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IOut", "IOut").WithLocation(11, 47)); } [Fact] public void IdentityConversion_Return_02() { var source = @"#pragma warning disable 1998 using System.Threading.Tasks; interface I { } interface IIn { } interface IOut { } class C { static async Task> F(I x) => x; static async Task> F(IIn x) => x; static async Task> F(IOut x) => x; static async Task> G(I x) => x; static async Task> G(IIn x) => x; static async Task> G(IOut x) => x; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,53): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static async Task> F(I x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(8, 53), // (9,57): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // static async Task> F(IIn x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(9, 57), // (11,53): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static async Task> G(I x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(11, 53), // (13,59): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // static async Task> G(IOut x) => x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IOut", "IOut").WithLocation(13, 59)); } [Fact] public void MakeMethodKeyForWhereMethod() { // this test verifies that a bad method symbol doesn't crash when generating a key for external annotations CSharpCompilation c = CreateCompilation(new[] { @" class Test { public void SimpleWhere() { int[] numbers = { 1, 2, 3 }; var lowNums = from n in numbers where n < 5 select n; } }" }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,33): error CS1935: Could not find an implementation of the query pattern for source type 'int[]'. 'Where' not found. Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'? // var lowNums = from n in numbers Diagnostic(ErrorCode.ERR_QueryNoProviderStandard, "numbers").WithArguments("int[]", "Where").WithLocation(7, 33) ); } [Fact] public void MaybeNullWhenTrue_Simple() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (IsNull(s)) { s.ToString(); // warn } else { s.ToString(); // ok } s.ToString(); // ok } public static bool IsNull([MaybeNullWhen(true)] string s) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void MaybeNullWhenTrue_Indexer() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { _ = this[s] ? s.ToString() // 1 : s.ToString(); } public bool this[[MaybeNullWhen(true)] string s] => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 15) ); } [Fact] public void MaybeNullWhenTrue_OutParameter_MiscTypes() { // Warn on misused nullability attributes (F3, F4 and F5)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static bool F1(T t, [MaybeNullWhen(true)]out T t2) => throw null!; static bool F2(T t, [MaybeNullWhen(true)]out T t2) where T : class => throw null!; static bool F3(T t, [MaybeNullWhen(true)]out T? t2) where T : class => throw null!; static bool F4(T t, [MaybeNullWhen(true)]out T t2) where T : struct => throw null!; static bool F5(T? t, [MaybeNullWhen(true)]out T? t2) where T : struct => throw null!; static void M1(T t1) { _ = F1(t1, out var s2) ? s2.ToString() // 1 : s2.ToString(); // 2 } static void M2(T t2) where T : class { _ = F1(t2, out var s3) ? s3.ToString() // 3 : s3.ToString(); _ = F2(t2, out var s4) ? s4.ToString() // 4 : s4.ToString(); _ = F3(t2, out var s5) ? s5.ToString() // 5 : s5.ToString(); // 6 t2 = null; // 7 _ = F1(t2, out var s6) ? s6.ToString() // 8 : s6.ToString(); // 9 _ = F2(t2, out var s7) // 10 ? s7.ToString() // 11 : s7.ToString(); // 12 _ = F3(t2, out var s8) // 13 ? s8.ToString() // 14 : s8.ToString(); // 15 } static void M3(T? t3) where T : class { _ = F1(t3, out var s9) ? s9.ToString() // 16 : s9.ToString(); // 17 _ = F2(t3, out var s10) // 18 ? s10.ToString() // 19 : s10.ToString(); // 20 _ = F3(t3, out var s11) // 21 ? s11.ToString() // 22 : s11.ToString(); // 23 if (t3 == null) return; _ = F1(t3, out var s12) ? s12.ToString() // 24 : s12.ToString(); _ = F2(t3, out var s13) ? s13.ToString() // 25 : s13.ToString(); _ = F3(t3, out var s14) ? s14.ToString() // 26 : s14.ToString(); // 27 } static void M4(T t4) where T : struct { _ = F1(t4, out var s15) ? s15.ToString() : s15.ToString(); _ = F4(t4, out var s16) ? s16.ToString() : s16.ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5, out var s17) ? s17.Value // 28 : s17.Value; // 29 _ = F5(t5, out var s18) ? s18.Value // 30 : s18.Value; // 31 if (t5 == null) return; _ = F1(t5, out var s19) ? s19.Value // 32 : s19.Value; // 33 _ = F5(t5, out var s20) ? s20.Value // 34 : s20.Value; // 35 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, source }); comp.VerifyDiagnostics( // (12,15): warning CS8602: Dereference of a possibly null reference. // ? s2.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 15), // (13,15): warning CS8602: Dereference of a possibly null reference. // : s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(13, 15), // (18,15): warning CS8602: Dereference of a possibly null reference. // ? s3.ToString() // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(18, 15), // (22,15): warning CS8602: Dereference of a possibly null reference. // ? s4.ToString() // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(22, 15), // (26,15): warning CS8602: Dereference of a possibly null reference. // ? s5.ToString() // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(26, 15), // (27,15): warning CS8602: Dereference of a possibly null reference. // : s5.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(27, 15), // (29,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 7 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(29, 14), // (31,15): warning CS8602: Dereference of a possibly null reference. // ? s6.ToString() // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s6").WithLocation(31, 15), // (32,15): warning CS8602: Dereference of a possibly null reference. // : s6.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s6").WithLocation(32, 15), // (34,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F2(t2, out var s7) // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(34, 13), // (35,15): warning CS8602: Dereference of a possibly null reference. // ? s7.ToString() // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s7").WithLocation(35, 15), // (36,15): warning CS8602: Dereference of a possibly null reference. // : s7.ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s7").WithLocation(36, 15), // (38,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F3(t2, out var s8) // 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(38, 13), // (39,15): warning CS8602: Dereference of a possibly null reference. // ? s8.ToString() // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s8").WithLocation(39, 15), // (40,15): warning CS8602: Dereference of a possibly null reference. // : s8.ToString(); // 15 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s8").WithLocation(40, 15), // (45,15): warning CS8602: Dereference of a possibly null reference. // ? s9.ToString() // 16 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s9").WithLocation(45, 15), // (46,15): warning CS8602: Dereference of a possibly null reference. // : s9.ToString(); // 17 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s9").WithLocation(46, 15), // (48,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F2(t3, out var s10) // 18 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(48, 13), // (49,15): warning CS8602: Dereference of a possibly null reference. // ? s10.ToString() // 19 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s10").WithLocation(49, 15), // (50,15): warning CS8602: Dereference of a possibly null reference. // : s10.ToString(); // 20 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s10").WithLocation(50, 15), // (52,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F3(t3, out var s11) // 21 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(52, 13), // (53,15): warning CS8602: Dereference of a possibly null reference. // ? s11.ToString() // 22 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s11").WithLocation(53, 15), // (54,15): warning CS8602: Dereference of a possibly null reference. // : s11.ToString(); // 23 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s11").WithLocation(54, 15), // (58,15): warning CS8602: Dereference of a possibly null reference. // ? s12.ToString() // 24 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s12").WithLocation(58, 15), // (62,15): warning CS8602: Dereference of a possibly null reference. // ? s13.ToString() // 25 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s13").WithLocation(62, 15), // (66,15): warning CS8602: Dereference of a possibly null reference. // ? s14.ToString() // 26 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s14").WithLocation(66, 15), // (67,15): warning CS8602: Dereference of a possibly null reference. // : s14.ToString(); // 27 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s14").WithLocation(67, 15), // (82,15): warning CS8629: Nullable value type may be null. // ? s17.Value // 28 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s17").WithLocation(82, 15), // (83,15): warning CS8629: Nullable value type may be null. // : s17.Value; // 29 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s17").WithLocation(83, 15), // (86,15): warning CS8629: Nullable value type may be null. // ? s18.Value // 30 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s18").WithLocation(86, 15), // (87,15): warning CS8629: Nullable value type may be null. // : s18.Value; // 31 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s18").WithLocation(87, 15), // (91,15): warning CS8629: Nullable value type may be null. // ? s19.Value // 32 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s19").WithLocation(91, 15), // (92,15): warning CS8629: Nullable value type may be null. // : s19.Value; // 33 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s19").WithLocation(92, 15), // (95,15): warning CS8629: Nullable value type may be null. // ? s20.Value // 34 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s20").WithLocation(95, 15), // (96,15): warning CS8629: Nullable value type may be null. // : s20.Value; // 35 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s20").WithLocation(96, 15) ); } [Fact] public void MaybeNullWhenTrue_FromMetadata() { var lib = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public static bool MaybeNullWhenTrue([MaybeNullWhen(true)] string s) => throw null!; } ", MaybeNullWhenAttributeDefinition }); var c = CreateNullableCompilation(@" public class D { public void Main(string s) { _ = C.MaybeNullWhenTrue(s) ? s.ToString() // 1 : s.ToString(); s.ToString(); } } ", references: new[] { lib.EmitToImageReference() }); c.VerifyDiagnostics( // (7,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 15) ); } [Fact] public void MaybeNullWhenFalse_FromMetadata() { var lib = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public static bool MaybeNullWhenFalse([MaybeNullWhen(false)] string s) => throw null!; } ", MaybeNullWhenAttributeDefinition }); var c = CreateNullableCompilation(@" public class D { public void Main(string s) { _ = C.MaybeNullWhenFalse(s) ? s.ToString() : s.ToString(); // 1 } } ", references: new[] { lib.EmitToImageReference() }); c.VerifyDiagnostics( // (8,15): warning CS8602: Dereference of a possibly null reference. // : s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 15) ); } [Fact] public void MaybeNullWhenFalse_TryGetValue() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class Optional { public void Main(Optional holder) { _ = holder.TryGetValue(out var item) ? item.ToString() : item.ToString(); // 1 item = null; } bool TryGetValue([MaybeNullWhen(false)] out T item) => throw null!; } ", MaybeNullWhenAttributeDefinition }); c.VerifyDiagnostics( // (9,15): warning CS8602: Dereference of a possibly null reference. // : item.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(9, 15) ); } [Fact] public void MaybeNull_TryGetValue() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class Optional { public void Main(Optional holder) { _ = holder.TryGetValue(out var item) ? item.ToString() // 1 : item.ToString(); // 2 item = null; } bool TryGetValue([MaybeNull] out T item) => throw null!; } ", MaybeNullAttributeDefinition }); c.VerifyDiagnostics( // (8,15): warning CS8602: Dereference of a possibly null reference. // ? item.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(8, 15), // (9,15): warning CS8602: Dereference of a possibly null reference. // : item.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "item").WithLocation(9, 15) ); } [Fact] public void NotNullWhenTrue_FromMetadata() { var lib = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public static bool NotNullWhenTrue([NotNullWhen(true)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }); var c = CreateNullableCompilation(@" public class D { public void Main(string? s) { _ = C.NotNullWhenTrue(s) ? s.ToString() : s.ToString(); // 1 } } ", references: new[] { lib.EmitToImageReference() }); c.VerifyDiagnostics( // (8,15): warning CS8602: Dereference of a possibly null reference. // : s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 15) ); } [Fact] public void NotNullWhenFalse_FromMetadata() { var lib = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public static bool NotNullWhenFalse([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }); var c = CreateNullableCompilation(@" public class D { public void Main(string? s) { _ = C.NotNullWhenFalse(s) ? s.ToString() // 1 : s.ToString(); } } ", references: new[] { lib.EmitToImageReference() }); c.VerifyDiagnostics( // (7,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 15) ); } [Fact] public void MaybeNullWhenTrue_OutParameter() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { string s; _ = M(out s) // 1 ? s.ToString() // 2 : s.ToString(); } public static bool M([MaybeNullWhen(true)] out string s) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // _ = M(out s) // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(8, 19), // (9,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 15) ); } [Fact] public void MaybeNull_OutParameter_InConditional() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { string s; _ = M(out s) // 1 ? s.ToString() // 2 : s.ToString(); // 3 } public static bool M([MaybeNull] out string s) => throw null!; } ", MaybeNullAttributeDefinition }, options: WithNonNullTypesTrue()); // Warn on misused nullability attributes (M)? https://github.com/dotnet/roslyn/issues/36073 c.VerifyDiagnostics( // (8,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // _ = M(out s) // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(8, 19), // (9,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 15), // (10,15): warning CS8602: Dereference of a possibly null reference. // : s.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(10, 15) ); } [Fact] public void MaybeNull_RefParameter_InConditional() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { string s = """"; _ = M(ref s) // 1 ? s.ToString() // 2 : s.ToString(); // 3 } public static bool M([MaybeNull] ref string s) => throw null!; } ", MaybeNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // _ = M(ref s) // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(8, 19), // (9,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 15), // (10,15): warning CS8602: Dereference of a possibly null reference. // : s.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(10, 15) ); } [Fact] public void MaybeNullWhenTrue_RefParameter() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { string s = """"; _ = M(ref s) // 1 ? s.ToString() // 2 : s.ToString(); } public static bool M([MaybeNullWhen(true)] ref string s) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // _ = M(ref s) // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(8, 19), // (9,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 15) ); } [Fact] public void MaybeNullWhenTrue_OnImplicitConversion() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class A { public static implicit operator C(A a) => throw null!; } public class C { public void Main() { A a = new A(); _ = IsNull(a) ? a.ToString() // 1 : a.ToString(); } public static bool IsNull([MaybeNullWhen(true)] C c) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // This warning is correct because we should be able to infer that `a` may be null when `(C)a` may be null c.VerifyDiagnostics( // (13,15): warning CS8602: Dereference of a possibly null reference. // ? a.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(13, 15) ); } [Fact] public void MaybeNullWhenTrue_OnImplicitConversion_ToNullable() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class A { public static implicit operator C?(A a) => throw null!; } public class C { public void Main() { A a = new A(); _ = IsNull(a) // 1 ? a.ToString() : a.ToString(); } public static bool IsNull([MaybeNullWhen(true)] C c) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // Unexpected second warning // We should not blindly strip conversions when learning that a value is null. // In this case, we shouldn't infer that `a` may be null from the fact that `(C)a` may be null in the when-true branch. // Tracked by https://github.com/dotnet/roslyn/issues/36164 c.VerifyDiagnostics( // (12,20): warning CS8604: Possible null reference argument for parameter 'c' in 'bool C.IsNull(C c)'. // _ = IsNull(a) // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a").WithArguments("c", "bool C.IsNull(C c)").WithLocation(12, 20), // (13,15): warning CS8602: Dereference of a possibly null reference. // ? a.ToString() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(13, 15) ); } [Fact] public void MaybeNullWhenTrue_OnExplicitConversion() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class A { public static explicit operator C(A a) => throw null!; } public class C { public void Main() { A a = new A(); _ = IsNull((C)a) ? a.ToString() // 1 : a.ToString(); } public static bool IsNull([MaybeNullWhen(true)] C c) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,15): warning CS8602: Dereference of a possibly null reference. // ? a.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(13, 15) ); } [Fact] public void MaybeNull_OnExplicitConversion() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class A { public static explicit operator C(A? a) => throw null!; } public class C { public void Main() { A a = new A(); _ = IsNull((C)a) ? a.ToString() : a.ToString(); } public static bool IsNull([MaybeNull] C c) => throw null!; } ", MaybeNullAttributeDefinition }, options: WithNonNullTypesTrue()); // Both diagnostics are unexpected // We should not blindly strip conversions when learning that a value is null. // In this case, we shouldn't infer that `a` may be null from the fact that `(C)a` may be null. // Tracked by https://github.com/dotnet/roslyn/issues/36164 c.VerifyDiagnostics( // (13,15): warning CS8602: Dereference of a possibly null reference. // ? a.ToString() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(13, 15), // (14,15): warning CS8602: Dereference of a possibly null reference. // : a.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(14, 15) ); } [Fact] public void MaybeNull_Property() { // Warn on misused nullability attributes (P3, P5)? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [MaybeNull]public TOpen P1 { get; set; } = default!; } public class CClass where TClass : class { [MaybeNull]public TClass P2 { get; set; } = null!; [MaybeNull]public TClass? P3 { get; set; } = null; } public class CStruct where TStruct : struct { [MaybeNull]public TStruct P4 { get; set; } [MaybeNull]public TStruct? P5 { get; set; } }"; var lib = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, lib_cs }); var source = @" class C { static void M1(T t1) { new COpen().P1.ToString(); // 1 } static void M2(T t2) where T : class { new COpen().P1.ToString(); // 2 new CClass().P2.ToString(); // 3 new CClass().P3.ToString(); // 4 } static void M4(T t4) where T : struct { new COpen().P1.ToString(); new CStruct().P4.ToString(); new COpen().P1.Value.ToString(); // 5 new CStruct().P5.Value.ToString(); // 6 } }"; var expected = new[] { // (6,9): warning CS8602: Dereference of a possibly null reference. // new COpen().P1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new COpen().P1").WithLocation(6, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // new COpen().P1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new COpen().P1").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // new CClass().P2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new CClass().P2").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // new CClass().P3.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new CClass().P3").WithLocation(12, 9), // (18,9): warning CS8629: Nullable value type may be null. // new COpen().P1.Value.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new COpen().P1").WithLocation(18, 9), // (19,9): warning CS8629: Nullable value type may be null. // new CStruct().P5.Value.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new CStruct().P5").WithLocation(19, 9) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, MaybeNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var copen = (NamedTypeSymbol)m.GlobalNamespace.GetMember("COpen"); var copenAttributes = copen.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(copenAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.NullableContextAttribute(1)", "System.Runtime.CompilerServices.NullableAttribute(0)" }, copenAttributes); } var property = copen.GetMembers().OfType().Single(); var propertyAttributes = property.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.MaybeNullAttribute" }, propertyAttributes); } else { AssertEx.Empty(propertyAttributes); } var getter = property.GetMethod; var getterAttributes = getter.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(getterAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.CompilerGeneratedAttribute" }, getterAttributes); } var getterReturnAttributes = getter.GetReturnTypeAttributes().Select(a => a.ToString()); Assert.Equal(FlowAnalysisAnnotations.MaybeNull, getter.ReturnTypeFlowAnalysisAnnotations); if (isSource) { AssertEx.Empty(getterReturnAttributes); } else { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.MaybeNullAttribute" }, getterReturnAttributes); } var setter = property.SetMethod; var setterAttributes = setter.GetAttributes(); if (isSource) { AssertEx.Empty(setterAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.CompilerGeneratedAttribute" }, setterAttributes.Select(a => a.ToString())); } Assert.Equal(FlowAnalysisAnnotations.None, setter.ReturnTypeFlowAnalysisAnnotations); var setterReturnAttributes = setter.GetReturnTypeAttributes(); AssertEx.Empty(setterReturnAttributes); } } [Fact] public void MaybeNull_Property_InCompoundAssignment() { var source = @" using System.Diagnostics.CodeAnalysis; class C { [MaybeNull] C Property { get; set; } = null!; public static C operator+(C one, C other) => throw null!; void M(C c) { Property += c; // 1 } }"; var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition }); comp.VerifyDiagnostics( // (10,9): warning CS8604: Possible null reference argument for parameter 'one' in 'C C.operator +(C one, C other)'. // Property += c; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "Property").WithArguments("one", "C C.operator +(C one, C other)").WithLocation(10, 9) ); } [Fact] public void MaybeNull_Property_WithNotNull() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; public class COpen { [MaybeNull, NotNull]public TOpen P1 { get; set; } = default!; }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, NotNullAttributeDefinition, source }); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var copen = (NamedTypeSymbol)m.GlobalNamespace.GetMember("COpen"); var copenAttributes = copen.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(copenAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.NullableContextAttribute(1)", "System.Runtime.CompilerServices.NullableAttribute(0)" }, copenAttributes); } var property = copen.GetMembers().OfType().Single(); var propertyAttributes = property.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.MaybeNullAttribute", "System.Diagnostics.CodeAnalysis.NotNullAttribute" }, propertyAttributes); } else { AssertEx.Empty(propertyAttributes); } var getter = property.GetMethod; var getterAttributes = getter.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(getterAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.CompilerGeneratedAttribute" }, getterAttributes); } var getterReturnAttributes = getter.GetReturnTypeAttributes().Select(a => a.ToString()); Assert.Equal(FlowAnalysisAnnotations.MaybeNull | FlowAnalysisAnnotations.NotNull, getter.ReturnTypeFlowAnalysisAnnotations); if (isSource) { AssertEx.Empty(getterReturnAttributes); } else { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.MaybeNullAttribute", "System.Diagnostics.CodeAnalysis.NotNullAttribute" }, getterReturnAttributes); } } } [Fact] public void MaybeNull_Property_WithExpressionBody() { // Warn on misused nullability attributes (P3, P5)? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [MaybeNull]public TOpen P1 => throw null!; } public class CClass where TClass : class { [MaybeNull]public TClass P2 => throw null!; [MaybeNull]public TClass? P3 => throw null!; } public class CStruct where TStruct : struct { [MaybeNull]public TStruct P4 => throw null!; [MaybeNull]public TStruct? P5 => throw null!; }"; var lib = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, lib_cs }); var source = @" class C { static void M1(T t1) { new COpen().P1.ToString(); // 1 } static void M2(T t2) where T : class { new COpen().P1.ToString(); // 2 new CClass().P2.ToString(); // 3 new CClass().P3.ToString(); // 4 } static void M4(T t4) where T : struct { new COpen().P1.ToString(); new CStruct().P4.ToString(); new COpen().P1.Value.ToString(); // 5 new CStruct().P5.Value.ToString(); // 6 } }"; var expected = new[] { // (6,9): warning CS8602: Dereference of a possibly null reference. // new COpen().P1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new COpen().P1").WithLocation(6, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // new COpen().P1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new COpen().P1").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // new CClass().P2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new CClass().P2").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // new CClass().P3.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new CClass().P3").WithLocation(12, 9), // (18,9): warning CS8629: Nullable value type may be null. // new COpen().P1.Value.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new COpen().P1").WithLocation(18, 9), // (19,9): warning CS8629: Nullable value type may be null. // new CStruct().P5.Value.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new CStruct().P5").WithLocation(19, 9) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, MaybeNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void MaybeNull_Property_OnVirtualProperty() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [MaybeNull] public virtual string P => throw null!; public virtual string P2 => throw null!; } public class C : Base { public override string P => throw null!; [MaybeNull] public override string P2 => throw null!; static void M(C c, Base b) { b.P.ToString(); // 1 c.P.ToString(); b.P2.ToString(); c.P2.ToString(); // 2 } }"; var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // b.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.P").WithLocation(15, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // c.P2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P2").WithLocation(19, 9) ); } [Fact] public void MaybeNull_Property_OnVirtualProperty_OnlyOverridingSetter() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [MaybeNull] public virtual string P { get { throw null!; } set { throw null!; } } public virtual string P2 { get { throw null!; } set { throw null!; } } } public class C : Base { public override string P { set { throw null!; } } [MaybeNull] public override string P2 { set { throw null!; } } static void M(C c, Base b) { b.P.ToString(); // 1 c.P.ToString(); // 2 b.P2.ToString(); c.P2.ToString(); } }"; var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // b.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.P").WithLocation(15, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // c.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(16, 9) ); } [Fact] public void MaybeNull_Property_OnVirtualProperty_OnlyOverridingGetter() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [MaybeNull] public virtual string P { get { throw null!; } set { throw null!; } } public virtual string P2 { get { throw null!; } set { throw null!; } } } public class C : Base { public override string P { get { throw null!; } } [MaybeNull] public override string P2 { get { throw null!; } } static void M(C c, Base b) { b.P.ToString(); // 1 c.P.ToString(); b.P2.ToString(); c.P2.ToString(); // 2 } }"; var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // b.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.P").WithLocation(15, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // c.P2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P2").WithLocation(19, 9) ); } [Fact] public void MaybeNull_Indexer() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [MaybeNull]public TOpen this[int i] { get => throw null!; } } public class CClass where TClass : class { [MaybeNull]public TClass this[int i] { get => throw null!; } } public class CClass2 where TClass : class { [MaybeNull]public TClass? this[int i] { get => throw null!; } } public class CStruct where TStruct : struct { [MaybeNull]public TStruct this[int i] { get => throw null!; } } public class CStruct2 where TStruct : struct { [MaybeNull]public TStruct? this[int i] { get => throw null!; } }"; var lib = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, lib_cs }); var source = @" class C { static void M1(T t1) { new COpen()[0].ToString(); // 1 } static void M2(T t2) where T : class { new COpen()[0].ToString(); // 2 new CClass()[0].ToString(); // 3 new CClass2()[0].ToString(); // 4 } static void M4(T t4) where T : struct { new COpen()[0].ToString(); new CStruct()[0].ToString(); new COpen()[0].Value.ToString(); // 5 new CStruct2()[0].Value.ToString(); // 6 } }"; var expected = new[] { // (6,9): warning CS8602: Dereference of a possibly null reference. // new COpen()[0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new COpen()[0]").WithLocation(6, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // new COpen()[0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new COpen()[0]").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // new CClass()[0].ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new CClass()[0]").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // new CClass2()[0].ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new CClass2()[0]").WithLocation(12, 9), // (18,9): warning CS8629: Nullable value type may be null. // new COpen()[0].Value.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new COpen()[0]").WithLocation(18, 9), // (19,9): warning CS8629: Nullable value type may be null. // new CStruct2()[0].Value.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new CStruct2()[0]").WithLocation(19, 9) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, MaybeNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void MaybeNull_Indexer_OnVirtualIndexer_OnlyOverridingSetter() { var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [MaybeNull] public virtual string this[int i] { get { throw null!; } set { throw null!; } } public virtual string this[byte i] { get { throw null!; } set { throw null!; } } } public class C : Base { public override string this[int i] { set { throw null!; } } [MaybeNull] public override string this[byte i] { set { throw null!; } } static void M(C c, Base b) { b[(int)0].ToString(); // 1 c[(int)0].ToString(); // 2 b[(byte)0].ToString(); c[(byte)0].ToString(); } }"; var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // b[(int)0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[(int)0]").WithLocation(15, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // c[(int)0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[(int)0]").WithLocation(16, 9) ); } [Fact] public void MaybeNull_Indexer_OnVirtualIndexer_OnlyOverridingGetter() { var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [MaybeNull] public virtual string this[int i] { get { throw null!; } set { throw null!; } } public virtual string this[byte i] { get { throw null!; } set { throw null!; } } } public class C : Base { public override string this[int i] { get { throw null!; } } [MaybeNull] public override string this[byte i] { get { throw null!; } } static void M(C c, Base b) { b[(int)0].ToString(); // 1 c[(int)0].ToString(); b[(byte)0].ToString(); c[(byte)0].ToString(); // 2 } }"; var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // b[(int)0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[(int)0]").WithLocation(15, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // c[(byte)0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[(byte)0]").WithLocation(19, 9) ); } [Fact] public void MaybeNull_Indexer_Implementation() { // Should we enforce nullability annotation attributes inside method bodies? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class CClass where TClass : class { [MaybeNull]public TClass this[int i] { get => null; } // 1, maybe we shouldn't warn here }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (4,51): warning CS8603: Possible null reference return. // [MaybeNull]public TClass this[int i] { get => null; } // 1, maybe we shouldn't warn here Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(4, 51) ); } [Fact] public void MaybeNullWhenTrue_OnImplicitReferenceConversion() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class A : Base { } public class Base { public void Main() { A a = new A(); _ = IsNull(a) ? a.ToString() // 1 : a.ToString(); } public static bool IsNull([MaybeNullWhen(true)] Base b) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,15): warning CS8602: Dereference of a possibly null reference. // ? a.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(12, 15) ); } [Fact] public void MaybeNullWhenTrue_EqualsTrue() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (IsNull(s) == true) { s.ToString(); // warn } else { s.ToString(); // ok } s.ToString(); // ok } public static bool IsNull([MaybeNullWhen(true)] string s) => throw null!; } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // ok Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void MaybeNullWhenTrue_MaybeNullInitialState() { // Warn on misused nullability attributes (warn on IsNull)? https://github.com/dotnet/roslyn/issues/36073 var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (IsNull(s)) { s.ToString(); // 1 } else { s.ToString(); // 2 } } public static bool IsNull([MaybeNullWhen(true)] string? s) => throw null!; } ", MaybeNullWhenAttributeDefinition }); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void MaybeNullWhenTrue_MaybeNullWhenFalseOnSameParameter() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (IsNull(s)) { s.ToString(); // 1 } else { s.ToString(); // MaybeNullWhen(false) was ignored } } public static bool IsNull([MaybeNullWhen(true), MaybeNullWhen(false)] string s) => throw null!; // 2 } ", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (16,53): error CS0579: Duplicate 'MaybeNullWhen' attribute // public static bool IsNull([MaybeNullWhen(true), MaybeNullWhen(false)] string s) => throw null!; // 2 Diagnostic(ErrorCode.ERR_DuplicateAttribute, "MaybeNullWhen").WithArguments("MaybeNullWhen").WithLocation(16, 53) ); } [Fact] public void MaybeNullWhenTrue_MaybeNullOnSameParameter() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (IsNull(s)) { s.ToString(); // 1 } else { s.ToString(); // 2 } } public static bool IsNull([MaybeNullWhen(true), MaybeNull] string s) => throw null!; } ", MaybeNullWhenAttributeDefinition, MaybeNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void MaybeNullWhenTrue_NotNullWhenTrueOnSecondParameter() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (M(s, s)) { s.ToString(); } else { s.ToString(); } s.ToString(); } public static bool M([MaybeNullWhen(true)] string s, [NotNullWhen(true)] string s2) => throw null!; } ", MaybeNullWhenAttributeDefinition, NotNullWhenAttributeDefinition }); // post-condition attributes are applied on arguments left-to-right c.VerifyDiagnostics(); } [Fact] public void NotNullWhenTrue_MaybeNullWhenTrueOnSecondParameter() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (M(s, s)) { s.ToString(); // 1 } else { s.ToString(); } } public static bool M([NotNullWhen(true)] string s, [MaybeNullWhen(true)] string s2) => throw null!; } ", MaybeNullWhenAttributeDefinition, NotNullWhenAttributeDefinition }); // Warn on misused nullability attributes (warn on first parameter of M)? https://github.com/dotnet/roslyn/issues/36073 // post-condition attributes are applied on arguments left-to-right c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void NotNullWhenFalse_MaybeNullWhenFalseOnSecondParameter() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s) { if (M(s, s)) { s.ToString(); } else { s.ToString(); // 1 } } public static bool M([NotNullWhen(false)] string s, [MaybeNullWhen(false)] string s2) => throw null!; } ", MaybeNullWhenAttributeDefinition, NotNullWhenAttributeDefinition }); // Warn on misused nullability attributes (warn on first parameter of M)? https://github.com/dotnet/roslyn/issues/36073 // post-condition attributes are applied on arguments left-to-right c.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void MaybeNullWhenFalse_NotNullWhenFalseOnSecondParameter() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (M(s, s)) { s.ToString(); // 1 } else { s.ToString(); } } public static bool M([MaybeNullWhen(false)] string? s, [NotNullWhen(false)] string? s2) => throw null!; } ", MaybeNullWhenAttributeDefinition, NotNullWhenAttributeDefinition }); // Warn on misused nullability attributes (warn on first parameter of M)? https://github.com/dotnet/roslyn/issues/36073 // post-condition attributes are applied on arguments left-to-right c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void NotNullWhenTrue_RefParameter() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { string? s = null; _ = M(ref s) ? s.ToString() : s.ToString(); // 1 } public static bool M([NotNullWhen(true)] ref string? s) => throw null!; } ", NotNullWhenAttributeDefinition }); c.VerifyDiagnostics( // (10,15): warning CS8602: Dereference of a possibly null reference. // : s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(10, 15) ); } [Fact] public void NotNullWhenFalse_OutParameter_MiscTypes() { // Warn on misused nullability attributes (F2, F4)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static bool F1(T t, [NotNullWhen(false)]out T t2) => throw null!; static bool F2(T t, [NotNullWhen(false)]out T t2) where T : class => throw null!; static bool F3(T t, [NotNullWhen(false)]out T? t2) where T : class => throw null!; static bool F4(T t, [NotNullWhen(false)]out T t2) where T : struct => throw null!; static bool F5(T? t, [NotNullWhen(false)]out T? t2) where T : struct => throw null!; static void M1(T t1) { _ = F1(t1, out var s2) ? s2.ToString() // 1 : s2.ToString(); } static void M2(T t2) where T : class { _ = F1(t2, out var s3) ? s3.ToString() : s3.ToString(); _ = F2(t2, out var s4) ? s4.ToString() : s4.ToString(); _ = F3(t2, out var s5) ? s5.ToString() // 2 : s5.ToString(); t2 = null; // 3 _ = F1(t2, out var s6) ? s6.ToString() // 4 : s6.ToString(); _ = F2(t2, out var s7) // 5 ? s7.ToString() // 6 : s7.ToString(); _ = F3(t2, out var s8) // 7 ? s8.ToString() // 8 : s8.ToString(); } static void M3(T? t3) where T : class { _ = F1(t3, out var s9) ? s9.ToString() // 9 : s9.ToString(); _ = F2(t3, out var s10) // 10 ? s10.ToString() // 11 : s10.ToString(); _ = F3(t3, out var s11) // 12 ? s11.ToString() // 13 : s11.ToString(); if (t3 == null) return; _ = F1(t3, out var s12) ? s12.ToString() : s12.ToString(); _ = F2(t3, out var s13) ? s13.ToString() : s13.ToString(); _ = F3(t3, out var s14) ? s14.ToString() // 14 : s14.ToString(); } static void M4(T t4) where T : struct { _ = F1(t4, out var s15) ? s15.ToString() : s15.ToString(); _ = F4(t4, out var s16) ? s16.ToString() : s16.ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5, out var s17) ? s17.Value // 15 : s17.Value; _ = F5(t5, out var s18) ? s18.Value // 16 : s18.Value; if (t5 == null) return; _ = F1(t5, out var s19) ? s19.Value // 17 : s19.Value; _ = F5(t5, out var s20) ? s20.Value // 18 : s20.Value; } }"; var comp = CreateNullableCompilation(new[] { NotNullWhenAttributeDefinition, source }); comp.VerifyDiagnostics( // (12,15): warning CS8602: Dereference of a possibly null reference. // ? s2.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 15), // (26,15): warning CS8602: Dereference of a possibly null reference. // ? s5.ToString() // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(26, 15), // (29,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(29, 14), // (31,15): warning CS8602: Dereference of a possibly null reference. // ? s6.ToString() // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s6").WithLocation(31, 15), // (34,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F2(t2, out var s7) // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(34, 13), // (35,15): warning CS8602: Dereference of a possibly null reference. // ? s7.ToString() // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s7").WithLocation(35, 15), // (38,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F3(t2, out var s8) // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(38, 13), // (39,15): warning CS8602: Dereference of a possibly null reference. // ? s8.ToString() // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s8").WithLocation(39, 15), // (45,15): warning CS8602: Dereference of a possibly null reference. // ? s9.ToString() // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s9").WithLocation(45, 15), // (48,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F2(t3, out var s10) // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(48, 13), // (49,15): warning CS8602: Dereference of a possibly null reference. // ? s10.ToString() // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s10").WithLocation(49, 15), // (52,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = F3(t3, out var s11) // 12 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(52, 13), // (53,15): warning CS8602: Dereference of a possibly null reference. // ? s11.ToString() // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s11").WithLocation(53, 15), // (66,15): warning CS8602: Dereference of a possibly null reference. // ? s14.ToString() // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s14").WithLocation(66, 15), // (82,15): warning CS8629: Nullable value type may be null. // ? s17.Value // 15 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s17").WithLocation(82, 15), // (86,15): warning CS8629: Nullable value type may be null. // ? s18.Value // 16 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s18").WithLocation(86, 15), // (91,15): warning CS8629: Nullable value type may be null. // ? s19.Value // 17 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s19").WithLocation(91, 15), // (95,15): warning CS8629: Nullable value type may be null. // ? s20.Value // 18 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s20").WithLocation(95, 15) ); } [Fact] public void NotNullWhenFalse_OutParameter() { var c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { string? s; _ = M(out s) ? s.ToString() // 1 : s.ToString(); } public static bool M([NotNullWhen(false)] out string? s) => throw null!; } ", NotNullWhenAttributeDefinition }); c.VerifyDiagnostics( // (9,15): warning CS8602: Dereference of a possibly null reference. // ? s.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 15) ); } [Fact] [WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")] public void NotNullWhenFalse_EqualsTrue() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (MyIsNullOrEmpty(s) == true) { s.ToString(); // warn } else { s.ToString(); // ok } s.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // ok Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void NotNullWhenFalse_Nested() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (MyIsNullOrEmpty(s?.ToString())) { s.ToString(); // warn } else { s.ToString(); } } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact, WorkItem(32335, "https://github.com/dotnet/roslyn/issues/32335")] public void NotNullWhenTrue_LearnFromNonNullTest() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void M(C? c1) { if (MyIsNullOrEmpty(c1?.Method())) c1.ToString(); // 1 else c1.ToString(); } C? Method() => throw null!; static bool MyIsNullOrEmpty([NotNullWhen(false)] C? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // c1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(8, 13) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void NotNullWhenFalse_EqualsTrue_InErrorInvocation() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (Missing(MyIsNullOrEmpty(s))) { s.ToString(); // 1 } else { s.ToString(); // 2 } s.ToString(); } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,13): error CS0103: The name 'Missing' does not exist in the current context // if (Missing(MyIsNullOrEmpty(s))) Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(7, 13), // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] [WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")] public void NotNullWhenFalse_EqualsFalse() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (false == MyIsNullOrEmpty(s)) { s.ToString(); // ok } else { s.ToString(); // warn } s.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // ok Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] [WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")] public void NotNullWhenFalse_NotEqualsFalse() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (false != MyIsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } s.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // ok Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void NotNullWhenFalse_RequiresBoolReturn() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public static object MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotations(c, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_RequiresBoolReturn_OnGenericMethod() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s) { if (MyIsNullOrEmpty(s, true)) { s.ToString(); // warn } else { s.ToString(); // ok } } public static T MyIsNullOrEmpty([NotNullWhen(false)] string? s, T t) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void MethodWithOutNullableParameter_AfterNotNullWhenTrue() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (M(s, out string? s2)) { s.ToString(); // ok s2.ToString(); // warn } else { s.ToString(); // warn 2 s2.ToString(); // warn 3 } s.ToString(); // ok s2.ToString(); // ok } public static bool M([NotNullWhen(true)] string? s, out string? s2) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(10, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(15, 13) ); } [Fact] public void MethodWithOutNullableParameter_AfterNotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (M(s, out string? s2)) { s.ToString(); // ok s2.ToString(); // warn } else { s.ToString(); // ok s2.ToString(); // warn 2 } s.ToString(); // ok s2.ToString(); // ok } public static bool M([NotNull] string? s, out string? s2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(10, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(15, 13) ); } [Fact] public void MethodWithOutNullableParameter_AfterNotNull_InErrorInvocation() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (Missing(M(s, out string? s2))) { s.ToString(); s2.ToString(); // 1 } else { s.ToString(); s2.ToString(); // 2 } s.ToString(); s2.ToString(); } public static bool M([NotNull] string? s, out string? s2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,13): error CS0103: The name 'Missing' does not exist in the current context // if (Missing(M(s, out string? s2))) Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(7, 13), // (10,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(10, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(15, 13) ); } [Fact] public void MethodWithOutNonNullableParameter() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main() { M(out string s); s.ToString(); // ok } public static void M(out string value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void MethodWithOutNonNullableParameter_WithNullableOutArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main() { M(out string? s); s.ToString(); // ok } public static void M(out string value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void MethodWithRefNonNullableParameter() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main() { string s = ""hello""; M(ref s); s.ToString(); // ok } public static void M(ref string value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void MethodWithRefNonNullableParameter_WithNullableRefArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? s) { M(ref s); // warn s.ToString(); } public static void M(ref string value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,15): warning CS8601: Possible null reference assignment. // M(ref s); // warn Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s").WithLocation(6, 15) ); } [Fact, WorkItem(34874, "https://github.com/dotnet/roslyn/issues/34874")] public void MethodWithRefNonNullableParameter_WithNonNullRefArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main() { string? s = ""hello""; M(ref s); s.ToString(); } public static void M(ref string value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void MethodWithRefNullableParameter_WithNonNullableRefArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string s) { M(ref s); // warn 1 s.ToString(); // warn 2 } public static void M(ref string? value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // M(ref s); // warn 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(6, 15), // (7,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithRefNullableParameter_WithNonNullableLocal() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main() { string s = ""hello""; M(ref s); // warn 1 s.ToString(); // warn 2 } public static void M(ref string? value) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // M(ref s); // warn 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(7, 15), // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] public void MethodWithOutParameter_WithNullableOut() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { if (TryGetValue(key, out var s)) { s/*T:string?*/.ToString(); // warn } else { s/*T:string?*/.ToString(); // warn 2 } s.ToString(); // ok } public static bool TryGetValue(string key, out string? value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(12, 13) ); } /// /// Check the inferred type of var from the semantic model, which currently means from initial binding. /// private static void VerifyOutVar(CSharpCompilation compilation, string expectedType) { if (SkipVerify(expectedType)) { return; } var tree = compilation.SyntaxTrees.First(); var model = compilation.GetSemanticModel(tree); var outVar = tree.GetRoot().DescendantNodes().OfType().Single(); var symbol = (LocalSymbol)model.GetSymbolInfo(outVar).Symbol; Assert.Equal(expectedType, symbol.TypeWithAnnotations.ToDisplayString(TypeWithAnnotations.TestDisplayFormat)); Assert.Null(model.GetDeclaredSymbol(outVar)); } /// /// Check the inferred type of var from the semantic model, which currently means from initial binding. /// private static void VerifyVarLocal(CSharpCompilation compilation, string expectedType) { if (SkipVerify(expectedType)) { return; } var tree = compilation.SyntaxTrees.First(); var model = compilation.GetSemanticModel(tree); var varDecl = tree.GetRoot().DescendantNodes().OfType().Where(d => d.Declaration.Type.IsVar).Single(); var variable = varDecl.Declaration.Variables.Single(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(variable); Assert.Equal(expectedType, symbol.TypeWithAnnotations.ToDisplayString(TypeWithAnnotations.TestDisplayFormat)); Assert.Null(model.GetSymbolInfo(variable).Symbol); } // https://github.com/dotnet/roslyn/issues/30150: VerifyOutVar and VerifyVarLocal are currently // checking the type and nullability from initial binding, but there are many cases where initial binding // sets nullability to unknown - in particular, for method type inference which is used in many // of the existing callers of these methods. Re-enable these methods when we're checking the // nullability from NullableWalker instead of initial binding. private static bool SkipVerify(string expectedType) { return expectedType.Contains('?') || expectedType.Contains('!'); } [Fact] public void MethodWithGenericOutParameter() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { Copy(key, out var s); s/*T:string?*/.ToString(); // warn } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string!"); // https://github.com/dotnet/roslyn/issues/29856: expecting string? c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericOutParameter_WithUnnecessarySuppression() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { Copy(key!, out var s); s/*T:string!*/.ToString(); } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void VarLocal_FromGenericMethod_WithUnnecessarySuppression() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { var s = Copy(key!); s/*T:string!*/.ToString(); } public static T Copy(T key) => throw null!; } " }, options: WithNonNullTypesTrue()); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 VerifyVarLocal(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void VarLocal_FromGenericMethod() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { var s = Copy(key); s/*T:string?*/.ToString(); // warn } public static T Copy(T key) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string!"); // https://github.com/dotnet/roslyn/issues/29856: expecting string? c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericOutParameter_WithNonNullArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { key = ""hello""; CopyOrDefault(key, out var s); s/*T:string!*/.ToString(); // ok } public static void CopyOrDefault(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void MethodWithGenericNullableOutParameter() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { CopyOrDefault(key, out var s); s/*T:string?*/.ToString(); // warn } public static void CopyOrDefault(T key, out T? value) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericNullableOutParameter_WithNullableArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { CopyOrDefault(key, out var s); s/*T:string?*/.ToString(); // warn } public static void CopyOrDefault(T key, out T? value) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (6,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.CopyOrDefault(T, out T?)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // CopyOrDefault(key, out var s); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "CopyOrDefault").WithArguments("C.CopyOrDefault(T, out T?)", "T", "string?").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericNullableOutParameter_WithNonNullArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { key = ""hello""; CopyOrDefault(key, out var s); s/*T:string?*/.ToString(); // warn } public static void CopyOrDefault(T key, out T? value) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] public void MethodWithGenericNullableArrayOutParameter() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { CopyOrDefault(key, out var s); s/*T:string?[]!*/[0].ToString(); // warn } public static void CopyOrDefault(T key, out T?[] value) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?[]!"); c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?[]!*/[0].ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s/*T:string?[]!*/[0]").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericNullableArrayOutParameter_WithNullableArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { CopyOrDefault(key, out var s); s/*T:string?[]!*/[0].ToString(); // warn } public static void CopyOrDefault(T key, out T?[] value) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?[]!"); c.VerifyTypes(); c.VerifyDiagnostics( // (6,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.CopyOrDefault(T, out T?[])'. Nullability of type argument 'string?' doesn't match 'class' constraint. // CopyOrDefault(key, out var s); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "CopyOrDefault").WithArguments("C.CopyOrDefault(T, out T?[])", "T", "string?").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?[]!*/[0].ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s/*T:string?[]!*/[0]").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericArrayOutParameter_WithNonNullableArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { CopyOrDefault(key, out var s); s/*T:string![]!*/[0].ToString(); // ok } public static void CopyOrDefault(T key, out T[] value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string![]!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] [WorkItem(29295, "https://github.com/dotnet/roslyn/issues/29295")] public void CatchException() { var c = CreateCompilation(@" class C { void M() { try { System.Console.WriteLine(); } catch (System.Exception e) { e.ToString(); } } } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(29295, "https://github.com/dotnet/roslyn/issues/29295")] public void CatchException_WithWhenIsOperator() { var c = CreateCompilation(@" class C { void M() { try { System.Console.WriteLine(); } catch (System.Exception e) when (!(e is System.ArgumentException)) { e.ToString(); } } } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(29295, "https://github.com/dotnet/roslyn/issues/29295")] public void CatchException_NullableType() { var c = CreateCompilation(@" class C { void M() { try { System.Console.WriteLine(); } catch (System.Exception? e) { var e2 = Copy(e); e2.ToString(); e2 = null; // 1 e.ToString(); } } static U Copy(U u) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (14,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // e2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 18)); } [Fact] [WorkItem(29295, "https://github.com/dotnet/roslyn/issues/33540")] public void CatchException_ConstrainedGenericTypeParameter() { var c = CreateCompilation(@" class C { static void M() where T : System.Exception? { try { } catch (T e) { var e2 = Copy(e); e2.ToString(); // 1 e.ToString(); } } static U Copy(U u) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // e2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e2").WithLocation(12, 13)); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_TopLevelNullability() { var c = CreateCompilation(@" class C { public void M() { string? s = """"; M(ref s); s.ToString(); // 1 string s2 = """"; M(ref s2); // 2 s2.ToString(); // 3 string s3 = null; // 4 M2(ref s3); // 5 s3.ToString(); } void M(ref string? s) => throw null!; void M2(ref string s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9), // (11,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // M(ref s2); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s2").WithLocation(11, 15), // (12,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 9), // (14,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string s3 = null; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 21), // (15,16): warning CS8601: Possible null reference assignment. // M2(ref s3); // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s3").WithLocation(15, 16) ); } [Fact] public void RefParameter_WarningKind() { var c = CreateCompilation(@" class C { string field = """"; public void M() { string local = """"; M(ref local); // 1, W-warning M(ref field); // 2 M(ref RefString()); // 3 } ref string RefString() => throw null!; void M(ref string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // M(ref local); // 1, W-warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "local").WithLocation(8, 15), // (10,15): warning CS8601: Possible null reference assignment. // M(ref field); // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "field").WithLocation(10, 15), // (12,15): warning CS8601: Possible null reference assignment. // M(ref RefString()); // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "RefString()").WithLocation(12, 15) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_TopLevelNullability_AlwaysSet() { var c = CreateCompilation(@" class C { public void M() { string? s = null; M(ref s); s.ToString(); } void M(ref string s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,15): warning CS8601: Possible null reference assignment. // M(ref s); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s").WithLocation(7, 15) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_TopLevelNullability_Suppressed() { var c = CreateCompilation(@" class C { public void M() { string? s = """"; M(ref s!); s.ToString(); // no warning string s2 = """"; M(ref s2!); // no warning s2.ToString(); // no warning } void M(ref string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_VariousLValues() { var c = CreateCompilation(@" class C { string field = """"; string Property { get; set; } = """"; public void M() { M(ref null); // 1 M(ref """"); // 2 M(ref field); // 3 field.ToString(); // 4 M(ref Property); // 5 Property = null; // 6 } void M(ref string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,15): error CS1510: A ref or out value must be an assignable variable // M(ref null); // 1 Diagnostic(ErrorCode.ERR_RefLvalueExpected, "null").WithLocation(8, 15), // (9,15): error CS1510: A ref or out value must be an assignable variable // M(ref ""); // 2 Diagnostic(ErrorCode.ERR_RefLvalueExpected, @"""""").WithLocation(9, 15), // (11,15): warning CS8601: Possible null reference assignment. // M(ref field); // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "field").WithLocation(11, 15), // (12,9): warning CS8602: Dereference of a possibly null reference. // field.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "field").WithLocation(12, 9), // (14,15): error CS0206: A property or indexer may not be passed as an out or ref parameter // M(ref Property); // 5 Diagnostic(ErrorCode.ERR_RefProperty, "Property").WithArguments("C.Property").WithLocation(14, 15), // (15,20): warning CS8625: Cannot convert null literal to non-nullable reference type. // Property = null; // 6 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 20) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_TopLevelNullability_Extension() { var c = CreateCompilation(@" public class C { public void M() { string? s = """"; this.M(ref s); s.ToString(); // 1 string s2 = """"; this.M(ref s2); // 2 s2.ToString(); // 3 } } public static class Extension { public static void M(this C c, ref string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9), // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // this.M(ref s2); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s2").WithLocation(11, 20), // (12,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 9) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_TopLevelNullability_Generic() { var c = CreateCompilation(@" class C { public void M() where T : new() { T t = new T(); M(ref t); t.ToString(); // 1 } void M(ref T t) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_TopLevelNullability_Generic_Suppressed() { var c = CreateCompilation(@" class C { public void M() where T : new() { T t = new T(); M(ref t!); t.ToString(); // no warning } void M(ref T t) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_NestedNullability() { var c = CreateCompilation(@" class C { public void M(C s, C s2) { M(ref s); s.ToString(); M(ref s2); // 1, 2 s2.ToString(); } void M(ref C s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,15): warning CS8620: Argument of type 'C' cannot be used as an input of type 'C' for parameter 's' in 'void C.M(ref C s)' due to differences in the nullability of reference types. // M(ref s2); // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2").WithArguments("C", "C", "s", "void C.M(ref C s)").WithLocation(9, 15)); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_EvaluationOrder() { var c = CreateCompilation(@" class C { public void M() { string? s = """"; var v1 = M(ref s, s); s.ToString(); // 1 v1.ToString(); s = null; var v2 = M(ref s, s); s.ToString(); // 2 v2.ToString(); // 3 s = null; var v3 = M2(ref s, s); // 4 s.ToString(); v3.ToString(); // 5 } U M(ref string? s, U u) => throw null!; U M2(ref string s, U u) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // v2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v2").WithLocation(14, 9), // (17,25): warning CS8601: Possible null reference assignment. // var v3 = M2(ref s, s); // 4 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s").WithLocation(17, 25), // (19,9): warning CS8602: Dereference of a possibly null reference. // v3.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v3").WithLocation(19, 9) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_EvaluationOrder_VisitLValuesOnce() { var c = CreateCompilation(@" class C { ref string? F(string? x) => throw null!; void G(ref string? s) => throw null!; public void M() { string s = """"; G(ref F(s = null)); } } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,16): warning CS0219: The variable 's' is assigned but its value is never used // string s = ""; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "s").WithArguments("s").WithLocation(8, 16), // (9,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // G(ref F(s = null)); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(9, 21) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void RefParameter_EvaluationOrder_VisitMultipleLValues() { var c = CreateCompilation(@" class C { void F(ref string? s) => throw null!; public void M(bool b) { string? s = """"; string? s2 = """"; F(ref (b ? ref s : ref s2)); s.ToString(); // 1 s2.ToString(); // 2 } } ", options: WithNonNullTypesTrue()); // Missing warnings // Need to track that an expression as an L-value corresponds to multiple slots // Relates to https://github.com/dotnet/roslyn/issues/33365 c.VerifyDiagnostics(); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_TopLevelNullability() { var c = CreateCompilation(@" class C { public void M() { string? s = """"; M(out s); s.ToString(); // 1 string s2 = """"; M(out s2); // 2 s2.ToString(); // 3 } void M(out string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9), // (11,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // M(out s2); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s2").WithLocation(11, 15), // (12,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 9) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_TopLevelNullability_DeclarationExpression() { var c = CreateCompilation(@" class C { public void M() { M(out string? s); s.ToString(); // 1 M(out string s2); // 2 s2.ToString(); // 3 } void M(out string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9), // (9,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // M(out string s2); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "string s2").WithLocation(9, 15), // (10,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(10, 9) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_TopLevelNullability_Suppressed() { var c = CreateCompilation(@" class C { public void M() { string? s = """"; M(out s!); s.ToString(); // no warning string s2 = """"; M(out s2!); // no warning s2.ToString(); // no warning } void M(out string? s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_TopLevelNullability_Generic() { var c = CreateCompilation(@" class C { public void M() where T : new() { T t = new T(); M(out t); t.ToString(); // 1 } void M(out T t) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_TopLevelNullability_Generic_Suppressed() { var c = CreateCompilation(@" class C { public void M() where T : new() { T t = new T(); M(out t!); t.ToString(); // no warning } void M(out T t) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_NestedNullability() { var c = CreateCompilation(@" class C { public void M(C s, C s2) { M(out s); s.ToString(); M(out s2); // 1 s2.ToString(); } void M(out C s) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,15): warning CS8624: Argument of type 'C' cannot be used as an output of type 'C' for parameter 's' in 'void C.M(out C s)' due to differences in the nullability of reference types. // M(out s2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "s2").WithArguments("C", "C", "s", "void C.M(out C s)").WithLocation(9, 15) ); } [Fact] [WorkItem(26739, "https://github.com/dotnet/roslyn/issues/26739")] public void OutParameter_EvaluationOrder() { var c = CreateCompilation(@" class C { public void M() { string? s = """"; var v1 = M(out s, s); s.ToString(); // 1 v1.ToString(); s = null; var v2 = M(out s, s); s.ToString(); // 2 v2.ToString(); // 3 s = null; var v3 = M2(out s, s); s.ToString(); v3.ToString(); // 4 } U M(out string? s, U u) => throw null!; U M2(out string s, U u) => throw null!; } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // v2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v2").WithLocation(14, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // v3.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v3").WithLocation(19, 9) ); } [Fact] public void MethodWithGenericArrayOutParameter_WithNonNullArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { key = ""hello""; CopyOrDefault(key, out var s); s/*T:string![]!*/[0].ToString(); // ok } public static void CopyOrDefault(T key, out T[] value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string![]!"); // https://github.com/dotnet/roslyn/issues/29856: expecting string?[]! c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void MethodWithGenericOutParameter_WithNotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? key) { Copy(key, out var s); // ok s/*T:string!*/.ToString(); // ok } public static void Copy(T key, [NotNull] out T value) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string!"); // https://github.com/dotnet/roslyn/issues/29856: T is inferred to string! instead of string?, so the `var` gets `string!` c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void MethodWithGenericNullableOutParameter_WithNotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? key) { Copy(key, out var s); // ok s/*T:string!*/.ToString(); // ok } public static void Copy(T key, [NotNull] out T? value) where T : class => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.Copy(T, out T?)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // Copy(key, out var s); // ok Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Copy").WithArguments("C.Copy(T, out T?)", "T", "string?").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericOutParameter_WithNullLiteralArgument_WithNonNullableString() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main() { Copy(null, out string s); // warn s/*T:string!*/.ToString(); // ok } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics( // (6,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // Copy(null, out string s); // warn Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 14) ); } [Fact] public void MethodWithGenericOutParameter_WithNonNullableArgument_WithNonNullableString() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { Copy(key, out string s); s/*T:string!*/.ToString(); } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] [WorkItem(29857, "https://github.com/dotnet/roslyn/issues/29857")] public void MethodWithGenericOutParameter_WithNullableArgument_WithNonNullableString() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { Copy(key, out string s); s/*T:string?*/.ToString(); } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Copy(key, out string s); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "string s").WithLocation(6, 23), // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericOutParameter_WithNonNullableArgument_WithNullableString() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { Copy(key, out string? s); s/*T:string?*/.ToString(); } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void MethodWithGenericOutParameter_WithNullableArgument_WithNullableString() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { Copy(key, out string? s); s/*T:string?*/.ToString(); // warn } public static void Copy(T key, out T value) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyOutVar(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void VarLocalFromGenericMethod() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string key) { var s = Copy(key); s/*T:string!*/.ToString(); // ok } public T Copy(T key) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void VarLocalFromGenericMethod_WithNullableArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { var s = Copy(key); s/*T:string?*/.ToString(); // warn } public T Copy(T key) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string!"); // https://github.com/dotnet/roslyn/issues/29856: expecting string? c.VerifyTypes(); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void VarLocalFromGenericMethod_WithNonNullArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { key = ""hello""; var s = Copy(key); s/*T:string!*/.ToString(); // ok } public T Copy(T key) => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void VarLocalFromGenericMethod_WithNullableReturn() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { var s = Copy(key); s/*T:string?*/.ToString(); // warn } public T? Copy(T key) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (6,17): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.Copy(T)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // var s = Copy(key); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Copy").WithArguments("C.Copy(T)", "T", "string?").WithLocation(6, 17), // (7,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void VarLocalFromGenericMethod_WithNullableReturn_WithNonNullArgument() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string? key) { key = ""hello""; var s = Copy(key); s/*T:string?*/.ToString(); // warn } public T? Copy(T key) where T : class => throw null!; } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string?"); c.VerifyTypes(); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s/*T:string?*/.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] [WorkItem(29858, "https://github.com/dotnet/roslyn/issues/29858")] public void GenericMethod_WithNotNullOnMethod() { CSharpCompilation c = CreateCompilation(@" using System.Diagnostics.CodeAnalysis; public class C { [NotNull] public static T Copy(T key) => throw null!; } " + NotNullAttributeDefinition); c.VerifyDiagnostics( // (5,6): error CS0592: Attribute 'NotNull' is not valid on this declaration type. It is only valid on 'property, indexer, field, parameter, return' declarations. // [NotNull] Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "NotNull").WithArguments("NotNull", "property, indexer, field, parameter, return").WithLocation(5, 6) ); } [Fact] [WorkItem(29862, "https://github.com/dotnet/roslyn/issues/29862")] public void SuppressedNullGivesNonNullResult() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string s) { s = null!; var s2 = s; s2 /*T:string!*/ .ToString(); // ok s2 = null; // warn } } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics( // (9,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s2 = null; // warn Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(9, 14) ); } [Fact] [WorkItem(29862, "https://github.com/dotnet/roslyn/issues/29862")] public void SuppressedDefaultGivesNonNullResult() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string s) { s = default!; // default! returns a non-null result var s2 = s; s2/*T:string!*/.ToString(); // ok } } " }, options: WithNonNullTypesTrue()); VerifyVarLocal(c, "string!"); c.VerifyTypes(); c.VerifyDiagnostics(); } [Fact] public void SuppressedObliviousValueGivesNonNullResult() { var libComp = CreateCompilation(@" public static class Static { public static string Oblivious = null; } ", parseOptions: TestOptions.Regular7); var comp = CreateCompilation(new[] { @" public class C { public void Main(string s, string? ns) { s = Static.Oblivious!; var s2 = s; s2/*T:string!*/.ToString(); // ok ns = Static.Oblivious!; ns.ToString(); // ok } } " }, options: WithNonNullTypesTrue(), references: new[] { libComp.EmitToImageReference() }); VerifyVarLocal(comp, "string!"); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void SuppressedValueGivesNonNullResult() { var comp = CreateCompilation(new[] { @" public class C { public void Main(string? ns, bool b) { var x1 = F(ns!); x1 /*T:string!*/ .ToString(); var listNS = List.Create(ns); listNS /*T:List!*/ .ToString(); var x2 = F2(listNS); x2 /*T:string!*/ .ToString(); } public T F(T? x) where T : class => throw null!; public T F2(List x) where T : class => throw null!; } public class List { public static List Create(T t) => throw null!; } public class List { } " }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void NestedNullabilityMismatchIgnoresSuppression() { var obliviousComp = CreateCompilation(@" public static class Static { public static string Oblivious = null; } ", parseOptions: TestOptions.Regular7); var comp = CreateCompilation(new[] { @" public class C { public void Main(string s, string? ns) { var o = Static.Oblivious; { var listS = List.Create(s); var listNS = List.Create(ns); listS /*T:List!*/ .ToString(); listNS /*T:List!*/ .ToString(); listS = listNS!; // 1 } { var listS = List.Create(s); var listO = List.Create(o); listO /*T:List!*/ .ToString(); listS = listO; // ok } { var listNS = List.Create(ns); var listS = List.Create(s); listNS = listS!; // 2 } { var listNS = List.Create(ns); var listO = List.Create(o); listNS = listO!; // 3 } { var listO = List.Create(o); var listNS = List.Create(ns); listO = listNS!; // 4 } { var listO = List.Create(o); var listS = List.Create(s); listO = listS; // ok } } } public class List { public static List Create(T t) => throw null!; } public class List { } " }, options: WithNonNullTypesTrue(), references: new[] { obliviousComp.EmitToImageReference() }); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void AssignNull() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string s) { s = null; // warn s.ToString(); // warn 2 } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // warn Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void AssignDefault() { CSharpCompilation c = CreateCompilation(new[] { @" public class C { public void Main(string s) { s = default; // warn s.ToString(); // warn 2 } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = default; // warn Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 9) ); } [Fact] public void NotNullWhenTrue_Simple() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string key) { if (TryGetValue(key, out string? s)) { s.ToString(); // ok } else { s.ToString(); // warn } s.ToString(); // ok } public static bool TryGetValue(string key, [NotNullWhen(true)] out string? value) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); VerifyAnnotationsAndMetadata(c, "C.Main", None); VerifyAnnotationsAndMetadata(c, "C.TryGetValue", None, NotNullWhenTrue); } [Fact] public void NotNullWhenTrue_Ref() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string key) { string? s = null; if (TryGetValue(key, ref s)) { s.ToString(); // ok } else { s.ToString(); // warn } } public static bool TryGetValue(string key, [NotNullWhen(true)] ref string? value) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (14,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 13) ); } [Fact] public void NotNullWhenTrue_Nested() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (IsNotNull(s?.ToString())) { s.ToString(); } else { s.ToString(); // warn } } public static bool IsNotNull([NotNullWhen(true)] string? value) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); } [Fact] public void NotNullWhenTrue_WithNotNullWhenFalse_WithVoidReturn() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main() { M(out string? s); s.ToString(); // 1 } public static void M([NotNullWhen(true), NotNullWhen(false)] out string? value) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9), // (10,46): error CS0579: Duplicate 'NotNullWhen' attribute // public static void M([NotNullWhen(true), NotNullWhen(false)] out string? value) => throw null!; Diagnostic(ErrorCode.ERR_DuplicateAttribute, "NotNullWhen").WithArguments("NotNullWhen").WithLocation(10, 46) ); VerifyAnnotations(c, "C.M", NotNullWhenTrue); } [Fact] public void AssertsTrue_NotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { MyAssert(c != null); c.ToString(); } void MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_NotNull_Nested() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { MyAssert(c?.ToString() != null); c.ToString(); } void MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void AssertsTrue_NotNull_InErrorInvocation() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { Missing(MyAssert(c != null)); c.ToString(); } void MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): error CS0103: The name 'Missing' does not exist in the current context // Missing(MyAssert(c != null)); Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(7, 9) ); } [Fact] public void AssertsTrue_NotNull_NullConditionalAccess() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { object? _o = null; void Main(C? c) { MyAssert(c?._o != null); c.ToString(); c._o.ToString(); } void MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_Null() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { MyAssert(c == null); c.ToString(); } void MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void AssertsTrue_Null_InErrorInvocation() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { Missing(MyAssert(c == null)); c.ToString(); } void MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): error CS0103: The name 'Missing' does not exist in the current context // Missing(MyAssert(c == null)); Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9) ); } [Fact] public void AssertsTrue_RefOutInParameters() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(bool b) { MyAssert(ref b, out bool b2, in b); } void MyAssert([AssertsTrue] ref bool condition, [AssertsFalse] out bool condition2, [AssertsTrue] in bool condition3) => throw null!; } ", AssertsTrueAttributeDefinition, AssertsFalseAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_WithAssertsFalse() { CSharpCompilation c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void M(string s, string? s2) { MyAssert(s == null); s.ToString(); // 1 MyAssert2(s2 != null); s2.ToString(); } void MyAssert([AssertsTrue, AssertsFalse] bool condition) => throw null!; void MyAssert2([AssertsFalse, AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition, AssertsFalseAttributeDefinition }); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] public void AssertsTrue_MethodWithReturnType() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { if (MyAssert(c != null)) { c.ToString(); } else { c.ToString(); } } bool MyAssert([AssertsTrue] bool condition) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_Debug_Assert1_NotNull() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(C? c) { System.Diagnostics.Debug.Assert(c != null); c.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_NotNullAndNotEmpty() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? c) { Assert(c != null && c != """"); c.ToString(); } static void Assert([AssertsTrue] bool b) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_Debug_Assert1_NotNullAndNotEmpty() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(string? c) { System.Diagnostics.Debug.Assert(c != null && c != """"); c.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_NotNullOrUnknown() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? c, bool b) { Assert(c != null || b); c.ToString(); } static void Assert([AssertsTrue] bool b) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9) ); } [Fact] public void AssertsTrue_Debug_Assert2_NotNull() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(C? c) { System.Diagnostics.Debug.Assert(c != null, ""hello""); c.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_Debug_Assert3_NotNull() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(C? c) { System.Diagnostics.Debug.Assert(c != null, ""hello"", ""world""); c.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_Debug_Assert4_NotNull() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(C? c) { System.Diagnostics.Debug.Assert(c != null, ""hello"", ""world"", new object[] { }); c.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsTrue_IsNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C c) { Assert(c == null, ""hello""); c.ToString(); } static void Assert([AssertsTrue] bool b, string message) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9) ); } [Fact] public void AssertsTrue_NoDuplicateDiagnostics() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { Assert(Method(null), ""hello""); c.ToString(); } bool Method(string x) => throw null!; static void Assert([AssertsTrue] bool b, string message) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,23): warning CS8625: Cannot convert null literal to non-nullable reference type. // Assert(Method(null), "hello"); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9) ); } [Fact] public void AssertsTrue_InTry() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { try { Assert(c != null, ""hello""); } catch { } c.ToString(); } static void Assert([AssertsTrue] bool b, string message) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(13, 9) ); } [Fact] public void AssertsTrue_WithNotNullWhenFalse() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s, string? s2) { Assert(!string.IsNullOrEmpty(s)); s.ToString(); // ok Assert(string.IsNullOrEmpty(s2)); s2.ToString(); // warn } static void Assert([AssertsTrue] bool b) => throw null!; } ", AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(11, 9) ); } [Fact] public void AssertsFalse_Null() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { MyAssert(c == null); c.ToString(); } void MyAssert([AssertsFalse] bool condition) => throw null!; } ", AssertsFalseAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AssertsFalse_NotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(C? c) { MyAssert(c != null); c.ToString(); } void MyAssert([AssertsFalse] bool condition) => throw null!; } ", AssertsFalseAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9) ); } [Fact] public void NotNullWhenFalse_Simple() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string? s) { if (MyIsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } s.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); VerifyAnnotationsAndMetadata(c, "C.Main", None); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_BoolReturn() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public static object MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotations(c, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_OnTwoParameters() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s, string? s2) { if (MyIsNullOrEmpty(s, s2)) { s.ToString(); // warn 1 s2.ToString(); // warn 2 } else { s.ToString(); // ok s2.ToString(); // ok } s.ToString(); // ok s2.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s, [NotNullWhen(false)] string? s2) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (10,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(10, 13) ); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNullWhenFalse, NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_WithNotNullWhenTrueOnSecondParameter() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s, string? s2) { if (MyIsNullOrEmpty(s, s2)) { s.ToString(); // warn 1 s2.ToString(); // ok } else { s.ToString(); // ok s2.ToString(); // warn 2 } s.ToString(); // ok s2.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s, [NotNullWhen(true)] string? s2) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(15, 13) ); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNullWhenFalse, NotNullWhenTrue); } [Fact] public void NotNullWhenFalse_OnIndexer() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s, int x) { if (this[s, x]) { s.ToString(); // warn } else { s.ToString(); // ok } s.ToString(); // ok } public bool this[[NotNullWhen(false)] string? s, int x] => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void NotNullWhenFalse_SecondArgumentDereferences() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { if (Method(s, s.ToString())) // warn 1 { s.ToString(); // ok } else { s.ToString(); // ok } } static bool Method([NotNullWhen(false)] string? s, string s2) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,23): warning CS8602: Dereference of a possibly null reference. // if (Method(s, s.ToString())) // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 23) ); } [Fact] public void NotNullWhenFalse_SecondArgumentAssigns() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { if (Method(s, s = null)) { s.ToString(); // 1 } else { s.ToString(); } } static bool Method([NotNullWhen(false)] string? s, string? s2) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void NotNullWhenFalse_MissingAttribute() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(string? s) { if (MyIsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // warn 2 } s.ToString(); // ok } static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (17,34): error CS0246: The type or namespace name 'NotNullWhenAttribute' could not be found (are you missing a using directive or an assembly reference?) // static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "NotNullWhen").WithArguments("NotNullWhenAttribute").WithLocation(17, 34), // (17,34): error CS0246: The type or namespace name 'NotNullWhen' could not be found (are you missing a using directive or an assembly reference?) // static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "NotNullWhen").WithArguments("NotNullWhen").WithLocation(17, 34), // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(12, 13) ); VerifyAnnotations(c, "C.MyIsNullOrEmpty", None); } private static void VerifyAnnotations(Compilation compilation, string memberName, params FlowAnalysisAnnotations[] expected) { var method = compilation.GetMember(memberName); Assert.True((object)method != null, $"Could not find method '{memberName}'"); var actual = method.Parameters.Select(p => p.FlowAnalysisAnnotations); Assert.Equal(expected, actual); } private void VerifyAnnotationsAndMetadata(Compilation compilation, string memberName, params FlowAnalysisAnnotations[] expected) { VerifyAnnotations(compilation, memberName, expected); // Also verify from metadata var compilation2 = CreateCompilation("", references: new[] { compilation.EmitToImageReference() }); VerifyAnnotations(compilation2, memberName, expected); } [Fact] public void NotNullWhenFalse_BadAttribute() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (MyIsNullOrEmpty(s)) { s.ToString(); // warn 1 } else { s.ToString(); // warn 2 } } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] public class NotNullWhenAttribute : Attribute { public NotNullWhenAttribute(bool when, bool other = false) { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", None); } [Fact] public void NotNullWhenFalse_InvertIf() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (!MyIsNullOrEmpty(s)) { s.ToString(); // ok } else { s.ToString(); // warn } } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13) ); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_WithNullLiteral() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { _ = MyIsNullOrEmpty(null); } static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNullWhenFalse_InstanceMethod() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (this.MyIsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } public bool MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_ExtensionMethod() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (this.MyIsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } } public static class Extension { public static bool MyIsNullOrEmpty(this C c, [NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); VerifyAnnotationsAndMetadata(c, "Extension.MyIsNullOrEmpty", None, NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_String_IsNullOrEmpty() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(string? s) { if (string.IsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13) ); VerifyAnnotationsAndMetadata(c, "System.String.IsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_String_IsNullOrEmpty_WithoutCorlib() { CSharpCompilation c = CreateEmptyCompilation(new[] { @" class C { void Main(string? s) { if (string.IsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } } namespace System { public class Object { public virtual string ToString() => throw null!; } public class String { public static bool IsNullOrEmpty(string? s) => throw null!; } public struct Void { } public struct Boolean { } public class ValueType { } public class Attribute { } public struct Enum { } public struct Int32 { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13) ); VerifyAnnotations(c, "System.String.IsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_String_IsNullOrEmpty_WithoutCorlib_RemovingAnnotations() { CSharpCompilation c = CreateEmptyCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { if (string.IsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } } namespace System { public class Object { public virtual string ToString() => throw null!; } public class String { public static bool IsNullOrEmpty([NotNullWhen(true)] string? s) => throw null!; } public struct Void { } public struct Boolean { } public class ValueType { } public class Enum { } public struct Int32 { } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); VerifyAnnotations(c, "System.String.IsNullOrEmpty", NotNullWhenFalse); } [Fact] public void ExtraAnnotationsWin() { CSharpCompilation c = CreateEmptyCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { System.Diagnostics.Debug.Assert(s != null, ""message""); s.ToString(); // ok } } namespace System { public class Object { public virtual string ToString() => throw null!; } public class String { } public struct Void { } public struct Boolean { } public class ValueType { } public class Enum { } public struct Int32 { } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } } namespace System.Diagnostics { public static class Debug { public static void Assert(bool condition, [NotNull] string message) => throw null!; } } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotations(c, "System.Diagnostics.Debug.Assert", AssertsTrue, None); } [Fact] public void NotNullWhenFalse_String_IsNullOrWhiteSpace_WithoutCorlib() { CSharpCompilation c = CreateEmptyCompilation(new[] { @" class C { void Main(string? s) { if (string.IsNullOrWhiteSpace(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } } namespace System { public class Object { public virtual string ToString() => throw null!; } public class String { public static bool IsNullOrWhiteSpace(string? s) => throw null!; } public struct Void { } public struct Boolean { } public class ValueType { } public class Attribute { } public struct Int32 { } public struct Enum { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13) ); VerifyAnnotations(c, "System.String.IsNullOrWhiteSpace", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_String_NotIsNullOrEmpty() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(string? s) { if (!string.IsNullOrEmpty(s)) { s.ToString(); // ok } else { s.ToString(); // warn } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(12, 13) ); VerifyAnnotationsAndMetadata(c, "System.String.IsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_String_NotIsNullOrEmpty_NoDuplicateWarnings() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void M() { if (!string.IsNullOrEmpty(M2(null))) { } } string? M2(string s) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // if (!string.IsNullOrEmpty(M2(null))) Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 38) ); } [Fact] public void NotNullWhenFalse_String_NotIsNullOrEmpty_NotAString() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void M() { if (!string.IsNullOrEmpty(M2(null))) { } } void M2(string s) => throw null!; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,35): error CS1503: Argument 1: cannot convert from 'void' to 'string' // if (!string.IsNullOrEmpty(M2(null))) Diagnostic(ErrorCode.ERR_BadArgType, "M2(null)").WithArguments("1", "void", "string").WithLocation(6, 35), // (6,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // if (!string.IsNullOrEmpty(M2(null))) Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 38) ); } [Fact] public void NotNullWhenFalse_String_IsNullOrWhiteSpace() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(string? s) { if (string.IsNullOrWhiteSpace(s)) { s.ToString(); // warn } else { s.ToString(); // ok } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13) ); VerifyAnnotationsAndMetadata(c, "System.String.IsNullOrWhiteSpace", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_PartialMethod() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public partial class C { partial void M1(string? s); partial void M1([NotNullWhen(false)] string? s) => throw null!; partial void M2([NotNullWhen(false)] string? s); partial void M2(string? s) => throw null!; partial void M3([NotNullWhen(false)] string? s); partial void M3([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,22): error CS0579: Duplicate 'NotNullWhen' attribute // partial void M3([NotNullWhen(false)] string? s); Diagnostic(ErrorCode.ERR_DuplicateAttribute, "NotNullWhen").WithArguments("NotNullWhen").WithLocation(11, 22) ); VerifyAnnotations(c, "C.M1", NotNullWhenFalse); VerifyAnnotations(c, "C.M2", NotNullWhenFalse); VerifyAnnotations(c, "C.M3", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_ReturningDynamic() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (MyIsNullOrEmpty(s)) { s.ToString(); // warn } else { s.ToString(); } } public dynamic MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); VerifyAnnotations(c, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_ReturningObject_FromMetadata() { string il = @" .class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldnull IL_0001: throw } } .class public auto ansi beforefieldinit C extends [mscorlib]System.Object { .method public hidebysig instance object MyIsNullOrEmpty (string s) cil managed { .param [1] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void System.Diagnostics.CodeAnalysis.NotNullWhenAttribute::.ctor(bool) = ( 01 00 00 00 00 ) IL_0000: ldnull IL_0001: throw } .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldnull IL_0001: throw } } .class public auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.NotNullWhenAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 00 08 00 00 01 00 54 02 0d 41 6c 6c 6f 77 4d 75 6c 74 69 70 6c 65 00 ) .method public hidebysig specialname rtspecialname instance void .ctor (bool when) cil managed { IL_0000: ldnull IL_0001: throw } } "; string source = @" public class D { void Main(C c, string? s) { if ((bool)c.MyIsNullOrEmpty(s)) { s.ToString(); // warn 1 } else { s.ToString(); // warn 2 } } } "; var compilation = CreateCompilationWithIL(new[] { source }, il, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(12, 13) ); VerifyAnnotations(compilation, "C.MyIsNullOrEmpty", NotNullWhenFalse); } [Fact] public void NotNullWhenFalse_ReturningObject() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { MyIsNullOrEmpty(s); s.ToString(); // warn } object MyIsNullOrEmpty([NotNullWhen(false)] string? s) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] public void NotNullWhenFalse_FollowedByNotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (MyIsNullOrEmpty(s, s)) { s.ToString(); // ok } else { s.ToString(); // ok } s.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false)] string? s, [NotNull] string? s2) => throw null!; } ", NotNullWhenAttributeDefinition, NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNullWhenFalse, NotNull); } [Fact] public void NotNullWhenFalse_AndNotNull() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { if (MyIsNullOrEmpty(s)) { s.ToString(); // ok } else { s.ToString(); // ok } s.ToString(); // ok } public static bool MyIsNullOrEmpty([NotNullWhen(false), NotNull] string? s) => throw null!; } ", NotNullWhenAttributeDefinition, NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotationsAndMetadata(c, "C.MyIsNullOrEmpty", NotNull); } [Fact] public void NotNull_Simple() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { ThrowIfNull(42, s); s.ToString(); // ok } public static void ThrowIfNull(int x, [NotNull] string? s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotationsAndMetadata(c, "C.ThrowIfNull", None, NotNull); } [Fact] public void NotNull_Nested() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { ThrowIfNull(s?.ToString()); s.ToString(); // ok } public static void ThrowIfNull([NotNull] string? s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact, WorkItem(32335, "https://github.com/dotnet/roslyn/issues/32335")] public void NotNull_LearningFromNotNullTest() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void M(C? c1) { ThrowIfNull(c1?.Method()); c1.ToString(); // ok } C? Method() => throw null!; static void ThrowIfNull([NotNull] C? c) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_ResettingStateMatters() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s, string? s2) { ThrowIfNull(s = s2, s2 = ""hello""); s.ToString(); // warn s2.ToString(); // ok } public static void ThrowIfNull(string? s1, [NotNull] string? s2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] public void NotNull_ResettingStateMatters_InIndexer() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s, string? s2) { _ = this[s = s2, s2 = ""hello""]; s.ToString(); // warn s2.ToString(); // ok } public int this[string? s1, [NotNull] string? s2] { get { throw null!; } } } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); } [Fact] public void NotNull_NoDuplicateDiagnosticsWhenResettingState() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public interface I { } public class C { void Main(string? s, I i) { ThrowIfNull(i, s); // single warning on conversion failure } public static void ThrowIfNull(I x, [NotNull] string? s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,21): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.ThrowIfNull(I x, string? s)'. // ThrowIfNull(i, s); // single warning on conversion failure Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "i").WithArguments("I", "I", "x", "void C.ThrowIfNull(I x, string? s)").WithLocation(8, 21) ); } [Fact] public void NotNull_Generic_WithRefType() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { ThrowIfNull(s); s.ToString(); // ok } public static void ThrowIfNull([NotNull] T s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_Generic_WithValueType() { CSharpCompilation c = CreateCompilation(@" using System.Diagnostics.CodeAnalysis; public class C { void Main(int s) { ThrowIfNull(s); s.ToString(); } public static void ThrowIfNull([NotNull] T s) => throw null!; } " + NotNullAttributeDefinition); c.VerifyDiagnostics(); } [Fact] public void NotNull_Generic_WithUnconstrainedGenericType() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(U u) { ThrowIfNull(u); u.ToString(); } public static void ThrowIfNull([NotNull] T s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_OnInterface() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s, Interface i) { i.ThrowIfNull(42, s); s.ToString(); // ok } } public interface Interface { void ThrowIfNull(int x, [NotNull] string? s); } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotationsAndMetadata(c, "Interface.ThrowIfNull", None, NotNull); } [Fact] public void NotNull_OnInterface_ImplementedWithoutAttribute() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C : Interface { void Main(string? s) { this.ThrowIfNull(42, s); s.ToString(); // warn ((Interface)this).ThrowIfNull(42, s); s.ToString(); // ok } public void ThrowIfNull(int x, string? s) => throw null!; } public interface Interface { void ThrowIfNull(int x, [NotNull] string? s); } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); VerifyAnnotationsAndMetadata(c, "Interface.ThrowIfNull", None, NotNull); VerifyAnnotationsAndMetadata(c, "C.ThrowIfNull", None, None); } [Fact] public void NotNull_OnInterface_ImplementedWithAttribute() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C : Interface { void Main(string? s) { ((Interface)this).ThrowIfNull(42, s); s.ToString(); // warn this.ThrowIfNull(42, s); s.ToString(); // ok } public void ThrowIfNull(int x, [NotNull] string? s) => throw null!; } public interface Interface { void ThrowIfNull(int x, string? s); } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9) ); VerifyAnnotationsAndMetadata(c, "Interface.ThrowIfNull", None, None); VerifyAnnotationsAndMetadata(c, "C.ThrowIfNull", None, NotNull); } [Fact] public void NotNull_OnDelegate() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; delegate void D([NotNull] object? o); public class C { void Main(string? s, D d) { d(s); s.ToString(); // ok } } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_WithParams() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { static void NotNull([NotNull] params object?[]? args) { } static void F(object? x, object? y, object[]? a) { NotNull(); a.ToString(); // warn 1 NotNull(x, y); x.ToString(); // warn 2 y.ToString(); // warn 3 NotNull(a); a.ToString(); // ok } } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(9, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // warn 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(13, 9) ); } [Fact] public void NotNullWhenTrue_WithParams() { CSharpCompilation c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { static bool NotNull([NotNullWhen(true)] params object?[]? args) => throw null!; static void F(object? x, object? y, object[]? a) { if (NotNull()) a.ToString(); // warn 1 if (NotNull(x, y)) { x.ToString(); // warn 2 y.ToString(); // warn 3 } if (NotNull(a)) a.ToString(); } } ", NotNullWhenAttributeDefinition }); c.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // warn 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(14, 13) ); } [Fact] public void NotNull_WithParamsOnFirstParameter() { CSharpCompilation c = CreateCompilationWithIL(new[] { @" public class D { static void F(object[]? a, object? b, object? c) { C.NotNull(a, b, c); a.ToString(); // ok b.ToString(); // warn 1 c.ToString(); // warn 2 } } " }, @" .class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: ret } .method public hidebysig specialname rtspecialname instance void .ctor ( bool[] '' ) cil managed { IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: ret } } .class public auto ansi beforefieldinit C extends [mscorlib]System.Object { .method public hidebysig static void NotNull ( object[] args, object[] args2 ) cil managed { .param [1] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(bool[]) = ( 01 00 02 00 00 00 01 01 00 00 ) .custom instance void System.Diagnostics.CodeAnalysis.NotNullAttribute::.ctor() = ( 01 00 00 00 ) .param [2] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(bool[]) = ( 01 00 02 00 00 00 01 01 00 00 ) .custom instance void System.Diagnostics.CodeAnalysis.NotNullAttribute::.ctor() = ( 01 00 00 00 ) IL_0000: nop IL_0001: ret } .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } } .class public auto ansi beforefieldinit System.Diagnostics.CodeAnalysis.NotNullAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.AttributeUsageAttribute::.ctor(valuetype [mscorlib]System.AttributeTargets) = ( 01 00 00 08 00 00 01 00 54 02 0d 41 6c 6c 6f 77 4d 75 6c 74 69 70 6c 65 00 ) .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret } } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // b.ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(9, 9) ); } [Fact] public void NotNull_WithNamedArguments() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { static void NotNull1([NotNull] object? x = null, object? y = null) { } static void NotNull2(object? x = null, [NotNull] object? y = null) { } static void F(object? x) { NotNull1(); NotNull1(y: x); x.ToString(); // warn NotNull2(y: x); x.ToString(); // ok } } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(11, 9) ); } [Fact] public void NotNull_OnDifferentTypes() { CSharpCompilation c = CreateCompilation(@" using System.Diagnostics.CodeAnalysis; public class C { public static void Bad([NotNull] int i) => throw null!; public static void ThrowIfNull([NotNull] T t) => throw null!; } " + NotNullAttributeDefinition); c.VerifyDiagnostics(); VerifyAnnotations(c, "C.Bad", NotNull); VerifyAnnotations(c, "C.ThrowIfNull", NotNull); } [Fact] public void NotNull_GenericMethod() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(T t) { t.ToString(); // warn ThrowIfNull(t); t.ToString(); // ok } public static void ThrowIfNull([NotNull] T s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(7, 9) ); VerifyAnnotationsAndMetadata(c, "C.ThrowIfNull", NotNull); } [Fact] [WorkItem(30079, "https://github.com/dotnet/roslyn/issues/30079")] public void NotNull_BeginInvoke() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public delegate void Delegate([NotNull] string? s); public class C { void M(Delegate d, string? s) { if (s != string.Empty) s.ToString(); // warn d.BeginInvoke(s, null, null); s.ToString(); } } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,32): warning CS8602: Dereference of a possibly null reference. // if (s != string.Empty) s.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 32) ); } [Fact] public void NotNull_BackEffect() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1, string? s2) { ThrowIfNull(s2 = s1, s1); s2.ToString(); // warn } public static void ThrowIfNull(string? x1, [NotNull] string? x2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29865: Should we be able to trace that s2 was assigned a non-null value? c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(8, 9) ); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void NotNull_InErrorInvocation() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1, string? s2) { Missing(ThrowIfNull(s1, s2 = s1)); s2.ToString(); } public static void ThrowIfNull([NotNull] string? x1, string? x2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,9): error CS0103: The name 'Missing' does not exist in the current context // Missing(ThrowIfNull(s1, s2 = s1)); Diagnostic(ErrorCode.ERR_NameNotInContext, "Missing").WithArguments("Missing").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(8, 9) ); } [Fact] public void NotNull_NoForwardEffect() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1, string? s2) { ThrowIfNull(s1, s2 = s1); s1.ToString(); s2.ToString(); // 1 } public static void ThrowIfNull([NotNull] string? x1, string? x2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); // NotNull is a post-condition so it comes after all the arguments have been evaluated c.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(9, 9) ); } [Fact] public void NotNull_NoForwardEffect2() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1) { ThrowIfNull(s1, s1 = null); s1.ToString(); } public static void ThrowIfNull([NotNull] string? x1, string? x2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_NoForwardEffect3() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1, string? s2) { ThrowIfNull(s1 = null, s2 = s1, s1 = """", s1); s2.ToString(); // warn } public static void ThrowIfNull(string? x1, string? x2, string? x3, [NotNull] string? x4) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(8, 9) ); } [Fact] public void NotNullWhenTrue_NoForwardEffect() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1, string? s2) { if (ThrowIfNull(s1, s2 = s1)) { s1.ToString(); s2.ToString(); // 1 } else { s1.ToString(); // 2 s2.ToString(); // 3 } } public static bool ThrowIfNull([NotNullWhen(true)] string? x1, string? x2) => throw null!; } ", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); // NotNullWhen is a post-condition so it comes after all the arguments have been evaluated c.VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(10, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // s1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(14, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(15, 13) ); } [Fact] [WorkItem(29867, "https://github.com/dotnet/roslyn/issues/29867")] public void NotNull_TypeInference() { // Nullability flow analysis attributes do not affect type inference CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void M(string? s1) { ThrowIfNull(s1, out var s2); s2/*T:string?*/.ToString(); } public static void ThrowIfNull([NotNull] T x1, out T x2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyTypes(); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // s2/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(8, 9) ); } [Fact] public void NotNull_ConditionalMethodInReleaseMode() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { ThrowIfNull(42, s); s.ToString(); // ok } [System.Diagnostics.Conditional(""DEBUG"")] static void ThrowIfNull(int x, [NotNull] string? s) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_SecondArgumentDereferences() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { void Main(string? s) { ThrowIfNull(s, s.ToString()); // warn s.ToString(); // ok } public static void ThrowIfNull([NotNull] string? s, string s2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (7,24): warning CS8602: Dereference of a possibly null reference. // ThrowIfNull(s, s.ToString()); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 24) ); VerifyAnnotationsAndMetadata(c, "C.ThrowIfNull", NotNull, None); } [Fact] public void NotNull_SecondArgumentAssigns() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { ThrowIfNull(s, s = null); s.ToString(); } static void ThrowIfNull([NotNull] string? s, string? s2) => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void NotNull_String_Contains() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Main(string? s) { ""hello"".Contains(s); s.ToString(); // ok } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); VerifyAnnotationsAndMetadata(c, "System.String.Contains", NotNull); } [Fact] public void NotNull_Indexer() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class C { void Main(string? s) { _ = this[42, s]; s.ToString(); // ok } public int this[int x, [NotNull] string? s] => throw null!; } ", NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void AllowNull_01() { // Warn on misused nullability attributes (all except F1)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([AllowNull]T t) { } static void F2([AllowNull]T t) where T : class { } static void F3([AllowNull]T t) where T : struct { } static void F4([AllowNull]T? t) where T : class { } static void F5([AllowNull]T? t) where T : struct { } static void M1(T t1) { F1(t1); } static void M2(T t2) where T : class { F1(t2); F2(t2); F4(t2); t2 = null; // 1 F1(t2); F2(t2); // 2 F4(t2); } static void M3(T? t3) where T : class { F1(t3); F2(t3); // 3 F4(t3); if (t3 == null) return; F1(t3); F2(t3); F4(t3); } static void M4(T t4) where T : struct { F1(t4); F3(t4); } static void M5(T? t5) where T : struct { F1(t5); F5(t5); if (t5 == null) return; F1(t5); F5(t5); } }"; var comp = CreateCompilation(new[] { AllowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); // The constraint warnings on F2(t2) and F2(t3) are not ideal but expected. comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (20,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(20, 9), // (26,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(26, 9)); } [Fact] public void AllowNull_WithMaybeNull() { // Warn on misused nullability attributes (AllowNull on type that could be marked with `?`, MaybeNull on an `in` or by-val parameter)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F0([AllowNull, MaybeNull]T t) { } static void F1([AllowNull, MaybeNull]ref T t) { } static void F2([AllowNull, MaybeNull]T t) where T : class { } static void F3([AllowNull, MaybeNull]T t) where T : struct { } static void F4([AllowNull, MaybeNull]T? t) where T : class { } static void F5([AllowNull, MaybeNull]T? t) where T : struct { } static void F6([AllowNull, MaybeNull]in T t) { } static void M(string? s1, string s2) { F0(s1); s1.ToString(); // 1 F0(s2); s2.ToString(); // 2 } static void M_WithRef(string? s1, string s2) { F1(ref s1); s1.ToString(); // 3 F1(ref s2); // 4 s2.ToString(); // 5 } }"; var comp = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // s1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(15, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(18, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // s1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(23, 9), // (25,24): warning CS8600: Converting null literal or possible null value to non-nullable type. // F1(ref s2); // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s2").WithLocation(25, 24), // (26,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(26, 9) ); } [Fact] public void AllowNull_02() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([AllowNull]T t) { } static void F2([AllowNull]T t) where T : class { } static void F3([AllowNull]T t) where T : struct { } static void F4([AllowNull]T? t) where T : class { } static void F5([AllowNull]T? t) where T : struct { } static void M1(T t1) { F1(t1); } static void M2(T t2) where T : class { F1(t2); F2(t2); F4(t2); t2 = null; // 1 F1(t2); F2(t2); F4(t2); } static void M3(T? t3) where T : class { F1(t3); F2(t3); F4(t3); if (t3 == null) return; F1(t3); F2(t3); F4(t3); } static void M4(T t4) where T : struct { F1(t4); F3(t4); } static void M5(T? t5) where T : struct { F1(t5); F5(t5); if (t5 == null) return; F1(t5); F5(t5); } }"; var comp = CreateCompilation(new[] { AllowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14)); } [Fact] public void AllowNull_03() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([AllowNull]string s) { } static void F2([AllowNull]string? s) { } static void M1(string s1) { F1(s1); F2(s1); s1 = null; // 1 F1(s1); F2(s1); } static void M2(string? s2) { F1(s2); F2(s2); if (s2 == null) return; F1(s2); F2(s2); } }"; var comp = CreateCompilation(new[] { AllowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 14)); } [Fact] public void AllowNull_RefParameter_03() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([AllowNull]ref string s) { } static void F2([AllowNull]ref string? s) { } static void M1() { string s1 = """"; F1(ref s1); s1.ToString(); string? s2 = """"; F2(ref s2); s2.ToString(); // 1 string s3 = null; // 2 F1(ref s3); s3.ToString(); string? s4 = null; F2(ref s4); s4.ToString(); // 3 } }"; var comp = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(14, 9), // (16,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string s3 = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(16, 21), // (22,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(22, 9) ); } [Fact] public void AllowNull_04() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([AllowNull]int i) { } static void F2([AllowNull]int? i) { } static void M1(int i1) { F1(i1); F2(i1); } static void M2(int? i2) { F2(i2); if (i2 == null) return; F2(i2); } }"; var comp = CreateCompilation(new[] { AllowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void AllowNull_05() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static void F1(T t) where T : class { } public static void F2([AllowNull]T t) where T : class { } }"; var comp = CreateCompilation(new[] { AllowNullAttributeDefinition, source0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x); // 2 F1(y); F2(x); // 3 F2(x!); F2(y); } }"; comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(x); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T)", "T", "object?").WithLocation(7, 9), // (9,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T)", "T", "object?").WithLocation(9, 9)); } [Fact] public void AllowNull_01_Property() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [AllowNull]public TOpen P1 { get; set; } = default!; } public class CClass where TClass : class { [AllowNull]public TClass P2 { get; set; } = null!; [AllowNull]public TClass? P3 { get; set; } = null; } public class CStruct where TStruct : struct { [AllowNull]public TStruct P4 { get; set; } [AllowNull]public TStruct? P5 { get; set; } }"; var lib = CreateNullableCompilation(new[] { lib_cs, AllowNullAttributeDefinition }); var source = @" class Program { static void M1(T t1) { new COpen().P1 = t1; } static void M2(T t2) where T : class { new COpen().P1 = t2; new CClass().P2 = t2; new CClass().P3 = t2; t2 = null; // 1 new COpen().P1 = t2; new CClass().P2 = t2; new CClass().P3 = t2; } static void M3(T? t3) where T : class { new COpen().P1 = t3; new CClass().P2 = t3; new CClass().P3 = t3; if (t3 == null) return; new COpen().P1 = t3; new CClass().P2 = t3; new CClass().P3 = t3; } static void M4(T t4) where T : struct { new COpen().P1 = t4; new CStruct().P4 = t4; } static void M5(T? t5) where T : struct { new COpen().P1 = t5; new CStruct().P5 = t5; if (t5 == null) return; new COpen().P1 = t5; new CStruct().P5 = t5; } }"; var expected = new[] { // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 14) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, AllowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void AllowNull_Operator_CompoundAssignment() { var source = @" using System.Diagnostics.CodeAnalysis; class CLeft { CLeft? Property { get; set; } public static CLeft? operator+([AllowNull] CLeft one, CLeft other) => throw null!; void M(CLeft c, CLeft? c2) { Property += c; Property += c2; // 1 } } class CRight { CRight Property { get { throw null!; } set { throw null!; } } // note not annotated public static CRight operator+(CRight one, [AllowNull] CRight other) => throw null!; void M(CRight c, CRight? c2) { Property += c; Property += c2; } } class CNone { CNone? Property { get; set; } public static CNone? operator+(CNone one, CNone other) => throw null!; void M(CNone c, CNone? c2) { Property += c; // 2 Property += c2; // 3, 4 } }"; var comp = CreateNullableCompilation(new[] { source, AllowNullAttributeDefinition }); comp.VerifyDiagnostics( // (11,21): warning CS8604: Possible null reference argument for parameter 'other' in 'CLeft? CLeft.operator +(CLeft one, CLeft other)'. // Property += c2; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "c2").WithArguments("other", "CLeft? CLeft.operator +(CLeft one, CLeft other)").WithLocation(11, 21), // (32,9): warning CS8604: Possible null reference argument for parameter 'one' in 'CNone? CNone.operator +(CNone one, CNone other)'. // Property += c; // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "Property").WithArguments("one", "CNone? CNone.operator +(CNone one, CNone other)").WithLocation(32, 9), // (33,9): warning CS8604: Possible null reference argument for parameter 'one' in 'CNone? CNone.operator +(CNone one, CNone other)'. // Property += c2; // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "Property").WithArguments("one", "CNone? CNone.operator +(CNone one, CNone other)").WithLocation(33, 9), // (33,21): warning CS8604: Possible null reference argument for parameter 'other' in 'CNone? CNone.operator +(CNone one, CNone other)'. // Property += c2; // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "c2").WithArguments("other", "CNone? CNone.operator +(CNone one, CNone other)").WithLocation(33, 21) ); } [Fact] public void AllowNull_01_Indexer() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [AllowNull]public TOpen this[int i] { set => throw null!; } } public class CClass where TClass : class { [AllowNull]public TClass this[int i] { set => throw null!; } } public class CClass2 where TClass : class { [AllowNull]public TClass? this[int i] { set => throw null!; } } public class CStruct where TStruct : struct { [AllowNull]public TStruct this[int i] { set => throw null!; } } public class CStruct2 where TStruct : struct { [AllowNull]public TStruct? this[int i] { set => throw null!; } }"; var lib = CreateNullableCompilation(new[] { lib_cs, AllowNullAttributeDefinition }); var source = @" class Program { static void M1(T t1) { new COpen()[0] = t1; } static void M2(T t2) where T : class { new COpen()[0] = t2; new CClass()[0] = t2; new CClass2()[0] = t2; t2 = null; // 1 new COpen()[0] = t2; new CClass()[0] = t2; new CClass2()[0] = t2; } static void M3(T? t3) where T : class { new COpen()[0] = t3; new CClass()[0] = t3; new CClass2()[0] = t3; if (t3 == null) return; new COpen()[0] = t3; new CClass()[0] = t3; new CClass2()[0] = t3; } static void M4(T t4) where T : struct { new COpen()[0] = t4; new CStruct()[0] = t4; } static void M5(T? t5) where T : struct { new COpen()[0] = t5; new CStruct2()[0] = t5; if (t5 == null) return; new COpen()[0] = t5; new CStruct2()[0] = t5; } }"; var expected = new[] { // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 14) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, AllowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var copen = (NamedTypeSymbol)m.GlobalNamespace.GetMember("COpen"); var copenAttributes = copen.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(copenAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.NullableContextAttribute(1)", "System.Runtime.CompilerServices.NullableAttribute(0)", "System.Reflection.DefaultMemberAttribute(\"Item\")" }, copenAttributes); } var property = copen.GetMembers().OfType().Single(); var propertyAttributes = property.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.AllowNullAttribute" }, propertyAttributes); } else { AssertEx.Empty(propertyAttributes); } var setter = property.SetMethod; var setterAttributes = setter.GetAttributes(); AssertEx.Empty(setterAttributes); var setterValueAttributes = setter.Parameters.Last().GetAttributes().Select(a => a.ToString()); Assert.Equal(FlowAnalysisAnnotations.AllowNull, setter.Parameters.Last().FlowAnalysisAnnotations); if (isSource) { AssertEx.Empty(setterValueAttributes); } else { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.AllowNullAttribute" }, setterValueAttributes); } Assert.Equal(FlowAnalysisAnnotations.None, setter.ReturnTypeFlowAnalysisAnnotations); var setterReturnAttributes = setter.GetReturnTypeAttributes(); AssertEx.Empty(setterReturnAttributes); } } [Fact] public void AllowNull_01_Indexer_WithDisallowNull() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [AllowNull, DisallowNull]public TOpen this[int i] { set => throw null!; } }"; var comp = CreateNullableCompilation(new[] { lib_cs, AllowNullAttributeDefinition, DisallowNullAttributeDefinition }); comp.VerifyDiagnostics(); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var copen = (NamedTypeSymbol)m.GlobalNamespace.GetMember("COpen"); var copenAttributes = copen.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(copenAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.NullableContextAttribute(1)", "System.Runtime.CompilerServices.NullableAttribute(0)", "System.Reflection.DefaultMemberAttribute(\"Item\")" }, copenAttributes); } var property = copen.GetMembers().OfType().Single(); var propertyAttributes = property.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.AllowNullAttribute", "System.Diagnostics.CodeAnalysis.DisallowNullAttribute" }, propertyAttributes); } else { AssertEx.Empty(propertyAttributes); } var setter = property.SetMethod; var setterAttributes = setter.GetAttributes(); AssertEx.Empty(setterAttributes); var setterValueAttributes = setter.Parameters.Last().GetAttributes().Select(a => a.ToString()); Assert.Equal(FlowAnalysisAnnotations.AllowNull | FlowAnalysisAnnotations.DisallowNull, setter.Parameters.Last().FlowAnalysisAnnotations); if (isSource) { AssertEx.Empty(setterValueAttributes); } else { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.DisallowNullAttribute", "System.Diagnostics.CodeAnalysis.AllowNullAttribute" }, setterValueAttributes); } } } [Fact] public void AllowNull_Indexer_OtherParameters() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class C { public string this[[AllowNull] string s] { set => throw null!; } } "; var lib = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new C()[s] = s2; new C()[s2] = s2; } }"; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, AllowNullAttributeDefinition }); comp2.VerifyDiagnostics(); } [Fact] public void AllowNull_Indexer_OtherParameters_OverridingSetter() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual string this[[AllowNull] string s] { set => throw null!; } } public class C : Base { public override string this[string s] { set => throw null!; } } "; var lib = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new C()[s] = s2; // 1 new C()[s2] = s2; } }"; var expected = new[] { // (6,17): warning CS8604: Possible null reference argument for parameter 's' in 'string C.this[string s]'. // new C()[s] = s2; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s").WithArguments("s", "string C.this[string s]").WithLocation(6, 17) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, AllowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void AllowNull_DoesNotAffectTypeInference() { var source = @"using System.Diagnostics.CodeAnalysis; public class A { public static void F1(T t, T t2) where T : class { } public static void F2([AllowNull]T t, T t2) where T : class { } static void Main() { object x = null; // 1 object? y = new object(); F1(x, x); // 2 F1(x, y); // 3 F1(y, y); F1(y, x); // 4 F2(x, x); // 5 F2(x, y); // 6 F2(y, y); F2(y, x); // 7 F2(x, x!); // 8 F2(x!, x); // 9 F2(x!, y); F2(y, x!); } }"; var comp = CreateNullableCompilation(new[] { source, AllowNullAttributeDefinition }); comp.VerifyDiagnostics( // (8,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 20), // (10,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(x, x); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T, T)", "T", "object?").WithLocation(10, 9), // (11,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(x, y); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T, T)", "T", "object?").WithLocation(11, 9), // (13,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(y, x); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T, T)", "T", "object?").WithLocation(13, 9), // (15,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x, x); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T, T)", "T", "object?").WithLocation(15, 9), // (16,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x, y); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T, T)", "T", "object?").WithLocation(16, 9), // (18,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(y, x); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T, T)", "T", "object?").WithLocation(18, 9), // (20,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x, x!); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T, T)", "T", "object?").WithLocation(20, 9), // (21,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T, T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x!, x); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T, T)", "T", "object?").WithLocation(21, 9) ); } [Fact] public void AllowNull_OHI_Parameter_Generic() { // Should we require nullability annotation attributes to match or vary properly in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual void F1([AllowNull]T t2) => throw null!; public virtual void F2([AllowNull]T t2) where T : class => throw null!; public virtual void F3([AllowNull]T? t2) where T : class => throw null!; public virtual void F4([AllowNull]T t2) where T : struct => throw null!; public virtual void F5([AllowNull]T? t2) where T : struct => throw null!; } public class Derived : Base { public override void F1(T t2) => throw null!; public override void F2(T t2) where T : class => throw null!; public override void F3(T? t2) where T : class => throw null!; public override void F4(T t2) where T : struct => throw null!; public override void F5(T? t2) where T : struct => throw null!; } "; var comp = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void DisallowNull_Parameter_01() { // Warn on misused nullability attributes (F2, F3, F4)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull]T t) { } static void F2([DisallowNull]T t) where T : class { } static void F3([DisallowNull]T? t) where T : class { } static void F4([DisallowNull]T t) where T : struct { } static void F5([DisallowNull]T? t) where T : struct { } static void M1(T t1) { F1(t1); } static void M2(T t2) where T : class { F1(t2); F2(t2); F3(t2); t2 = null; // 1 F1(t2); // 2 F2(t2); // 3, 4 F3(t2); // 5 } static void M3(T? t3) where T : class { F1(t3); // 6 F2(t3); // 7, 8 F3(t3); // 9 if (t3 == null) return; F1(t3); F2(t3); F3(t3); } static void M4(T t4) where T : struct { F1(t4); F4(t4); } static void M5(T? t5) where T : struct { F1(t5); // 10 F5(t5); // 11 if (t5 == null) return; F1(t5); F5(t5); } }"; var comp = CreateCompilation(new[] { DisallowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T? t)'. // F1(t2); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F1(T? t)").WithLocation(19, 12), // (20,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(20, 9), // (20,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T? t)'. // F2(t2); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F2(T? t)").WithLocation(20, 12), // (21,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T? t)'. // F3(t2); // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F3(T? t)").WithLocation(21, 12), // (25,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T? t)'. // F1(t3); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F1(T? t)").WithLocation(25, 12), // (26,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3); // 7, 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(26, 9), // (26,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T? t)'. // F2(t3); // 7, 8 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F2(T? t)").WithLocation(26, 12), // (27,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T? t)'. // F3(t3); // 9 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F3(T? t)").WithLocation(27, 12), // (40,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F1(t5); // 10 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(40, 12), // (41,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F5(t5); // 11 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(41, 12) ); } [Fact, WorkItem(36009, "https://github.com/dotnet/roslyn/issues/36009")] public void DisallowNull_Parameter_NullableValueType() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F5([DisallowNull]T? t) where T : struct { } static void M5(T? t5) where T : struct { F5(t5); // 1 if (t5 == null) return; F5(t5); } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (7,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F5(t5); Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(7, 12) ); } [Fact, WorkItem(36009, "https://github.com/dotnet/roslyn/issues/36009")] public void DisallowNull_RefParameter_NullableValueType() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F5([DisallowNull]ref T? t) where T : struct { } static void M5(T? t5) where T : struct { F5(ref t5); // 1 if (t5 == null) return; F5(ref t5); } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (7,16): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F5(ref t5); // 1 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(7, 16) ); } [Fact, WorkItem(36009, "https://github.com/dotnet/roslyn/issues/36009")] public void DisallowNull_InParameter_NullableValueType() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F5([DisallowNull]in T? t) where T : struct { } static void M5(T? t5) where T : struct { F5(in t5); // 1 if (t5 == null) return; F5(in t5); } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (7,15): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F5(in t5); // 1 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(7, 15) ); } [Fact, WorkItem(36009, "https://github.com/dotnet/roslyn/issues/36009")] public void DisallowNull_ByValParameter_NullableValueTypeViaConstraint() { var source = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual void M(U u) where U : T { } } public class C : Base> where T2 : struct { public override void M(U u) // U is constrained to be a Nullable type { M2(u); // 1 if (u is null) return; M2(u); } void M2([DisallowNull] T3 t) { } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (11,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // M2(u); // 1 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "u").WithLocation(11, 12) ); } [Fact] public void DisallowNull_Parameter_01_WithAllowNull() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull, AllowNull]T t) { } static void F2([DisallowNull, AllowNull]T t) where T : class { } static void F3([DisallowNull, AllowNull]T? t) where T : class { } static void F4([DisallowNull, AllowNull]T t) where T : struct { } static void F5([DisallowNull, AllowNull]T? t) where T : struct { } static void M1(T t1) { F1(t1); } static void M2(T t2) where T : class { F1(t2); F2(t2); F3(t2); t2 = null; // 1 F1(t2); // 2 F2(t2); // 3, 4 F3(t2); // 5 } static void M3(T? t3) where T : class { F1(t3); // 6 F2(t3); // 7, 8 F3(t3); // 9 if (t3 == null) return; F1(t3); F2(t3); F3(t3); } static void M4(T t4) where T : struct { F1(t4); F4(t4); } static void M5(T? t5) where T : struct { F1(t5); // 10 F5(t5); // 11 if (t5 == null) return; F1(t5); F5(t5); } }"; var comp = CreateCompilation(new[] { DisallowNullAttributeDefinition, AllowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T? t)'. // F1(t2); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F1(T? t)").WithLocation(19, 12), // (20,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(20, 9), // (20,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T? t)'. // F2(t2); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F2(T? t)").WithLocation(20, 12), // (21,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T? t)'. // F3(t2); // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F3(T? t)").WithLocation(21, 12), // (25,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T? t)'. // F1(t3); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F1(T? t)").WithLocation(25, 12), // (26,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3); // 7, 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(26, 9), // (26,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T? t)'. // F2(t3); // 7, 8 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F2(T? t)").WithLocation(26, 12), // (27,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T? t)'. // F3(t3); // 9 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F3(T? t)").WithLocation(27, 12), // (40,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F1(t5); // 10 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(40, 12), // (41,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F5(t5); // 11 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(41, 12) ); } [Fact, WorkItem(36009, "https://github.com/dotnet/roslyn/issues/36009")] public void DisallowNull_Parameter_02() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull]T t) { } static void F2([DisallowNull]T t) where T : class { } static void F3([DisallowNull]T? t) where T : class { } static void F4([DisallowNull]T t) where T : struct { } static void F5([DisallowNull]T? t) where T : struct { } static void M1(T t1) { F1(t1); } static void M2(T t2) where T : class { F1(t2); F2(t2); F3(t2); t2 = null; // 1 F1(t2); // 2 F2(t2); // 3 F3(t2); // 4 } static void M3(T? t3) where T : class { F1(t3); // 5 F2(t3); // 6 F3(t3); // 7 if (t3 == null) return; F1(t3); F2(t3); F3(t3); } static void M4(T t4) where T : struct { F1(t4); F4(t4); } static void M5(T? t5) where T : struct { F1(t5); // 8 F5(t5); // 9 if (t5 == null) return; F1(t5); F5(t5); } }"; var comp = CreateCompilation(new[] { DisallowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T t)'. // F1(t2); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F1(T t)").WithLocation(19, 15), // (20,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T t)'. // F2(t2); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F2(T t)").WithLocation(20, 15), // (21,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T? t)'. // F3(t2); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F3(T? t)").WithLocation(21, 15), // (25,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T t)'. // F1(t3); // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F1(T t)").WithLocation(25, 15), // (26,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T t)'. // F2(t3); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F2(T t)").WithLocation(26, 15), // (27,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T? t)'. // F3(t3); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F3(T? t)").WithLocation(27, 15), // (40,16): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F1(t5); // 8 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(40, 16), // (41,15): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F5(t5); // 9 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(41, 15) ); } [Fact] public void DisallowNull_Parameter_03() { // Warn on misused nullability attributes (F1, F2)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull]string s) { } static void F2([DisallowNull]string? s) { } static void M1(string s1) { F1(s1); F2(s1); s1 = null; // 1 F1(s1); // 2 F2(s1); // 3 } static void M2(string? s2) { F1(s2); // 4 F2(s2); // 5 if (s2 == null) return; F1(s2); F2(s2); } }"; var comp = CreateCompilation(new[] { DisallowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // s1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 14), // (11,12): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.F1(string s)'. // F1(s1); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s1").WithArguments("s", "void Program.F1(string s)").WithLocation(11, 12), // (12,12): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.F2(string? s)'. // F2(s1); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s1").WithArguments("s", "void Program.F2(string? s)").WithLocation(12, 12), // (16,12): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.F1(string s)'. // F1(s2); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s2").WithArguments("s", "void Program.F1(string s)").WithLocation(16, 12), // (17,12): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.F2(string? s)'. // F2(s2); // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s2").WithArguments("s", "void Program.F2(string? s)").WithLocation(17, 12)); } [Fact, WorkItem(36009, "https://github.com/dotnet/roslyn/issues/36009")] public void DisallowNull_Parameter_04() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull]int i) { } static void F2([DisallowNull]int? i) { } static void M1(int i1) { F1(i1); F2(i1); } static void M2(int? i2) { F2(i2); // 1 if (i2 == null) return; F2(i2); } }"; var comp = CreateCompilation(new[] { DisallowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,12): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // F2(i2); // 1 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "i2").WithLocation(13, 12) ); } [Fact] public void DisallowNull_Parameter_05() { // Warn on misused nullability attributes (F2)? https://github.com/dotnet/roslyn/issues/36073 var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static void F1(T? t) where T : class { } public static void F2([DisallowNull]T? t) where T : class { } }"; var comp = CreateCompilation(new[] { DisallowNullAttributeDefinition, source0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x); F1(y); F2(x); // 2 F2(y); } }"; comp = CreateNullableCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (9,12): warning CS8604: Possible null reference argument for parameter 't' in 'void A.F2(object? t)'. // F2(x); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void A.F2(object? t)").WithLocation(9, 12) ); } [Fact] public void DisallowNull_Parameter_OnOverride() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual void M([DisallowNull] string? s) { } } public class C : Base { public override void M(string? s) { } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new Base().M(s); // 1 new Base().M(s2); new C().M(s); new C().M(s2); } }"; var expected = new[] { // (6,22): warning CS8604: Possible null reference argument for parameter 's' in 'void Base.M(string? s)'. // new Base().M(s); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s").WithArguments("s", "void Base.M(string? s)").WithLocation(6, 22) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void DisallowNull_RefReturnValue_05() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static T? F1(T t) where T : class => throw null!; [return: DisallowNull] public static ref T? F2(T t) where T : class => throw null!; }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source0 }); comp.VerifyDiagnostics( // (5,14): error CS0592: Attribute 'DisallowNull' is not valid on this declaration type. It is only valid on 'property, indexer, field, parameter' declarations. // [return: DisallowNull] public static ref T? F2(T t) where T : class => throw null!; Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "DisallowNull").WithArguments("DisallowNull", "property, indexer, field, parameter").WithLocation(5, 14) ); var source1 = @"using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.All)] public sealed class DisallowNullAttribute : Attribute { } } public class A { public static ref T? F1(T t) where T : class => throw null!; [return: DisallowNull] public static ref T? F2(T t) where T : class => throw null!; static void Main() { object? y = new object(); F1(y) = y; F2(y) = y; // DisallowNull is ignored } }"; var comp2 = CreateNullableCompilation(source1); comp2.VerifyDiagnostics(); } [Fact] public void DisallowNull_OutParameter_03() { // Warn on misused nullability attributes (F1, F2)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull]out string t) => throw null!; static void F2([DisallowNull]out string? t) => throw null!; static void M() { F1(out string? t1); t1.ToString(); F2(out string? t2); t2.ToString(); // 1 } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // t2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(12, 9) ); } [Fact] public void DisallowNull_RefParameter_03() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([DisallowNull]ref string s) { } static void F2([DisallowNull]ref string? s) { } static void M1() { string s1 = """"; F1(ref s1); s1.ToString(); string? s2 = """"; F2(ref s2); s2.ToString(); // 1 string s3 = null; // 2 F1(ref s3); // 3 s3.ToString(); string? s4 = null; // 4 F2(ref s4); // 5 s4.ToString(); // 6 } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(14, 9), // (16,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string s3 = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(16, 21), // (17,16): warning CS8601: Possible null reference assignment. // F1(ref s3); // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s3").WithLocation(17, 16), // (21,16): warning CS8601: Possible null reference assignment. // F2(ref s4); // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s4").WithLocation(21, 16), // (22,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(22, 9) ); } [Fact] public void DisallowNull_Property() { // Warn on misused nullability attributes (P2, P3, P4)? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [DisallowNull]public TOpen P1 { get; set; } = default!; } public class CClass where TClass : class { [DisallowNull]public TClass P2 { get; set; } = null!; [DisallowNull]public TClass? P3 { get; set; } = null; } public class CStruct where TStruct : struct { [DisallowNull]public TStruct P4 { get; set; } [DisallowNull]public TStruct? P5 { get; set; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class C { static void M1(T t1) { new COpen().P1 = t1; } static void M2(T t2) where T : class { new COpen().P1 = t2; new CClass().P2 = t2; new CClass().P3 = t2; t2 = null; // 1 new COpen().P1 = t2; // 2 new CClass().P2 = t2; // 3 new CClass().P3 = t2; // 4, [DisallowNull] honored on TClass? } static void M3(T? t3) where T : class { new COpen().P1 = t3; // 5 new CClass().P2 = t3; // 6 new CClass().P3 = t3; // 7, [DisallowNull] honored on TClass? if (t3 == null) return; new COpen().P1 = t3; new CClass().P2 = t3; new CClass().P3 = t3; } static void M4(T t4) where T : struct { new COpen().P1 = t4; new CStruct().P4 = t4; } static void M5(T? t5) where T : struct { new COpen().P1 = t5; // 8 new CStruct().P5 = t5; // 9 if (t5 == null) return; new COpen().P1 = t5; new CStruct().P5 = t5; } }"; var expected = new[] { // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 14), // (14,29): warning CS8601: Possible null reference assignment. // new COpen().P1 = t2; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(14, 29), // (15,30): warning CS8601: Possible null reference assignment. // new CClass().P2 = t2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(15, 30), // (16,30): warning CS8601: Possible null reference assignment. // new CClass().P3 = t2; // 4, [DisallowNull] honored on TClass? Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(16, 30), // (20,29): warning CS8601: Possible null reference assignment. // new COpen().P1 = t3; // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(20, 29), // (21,30): warning CS8601: Possible null reference assignment. // new CClass().P2 = t3; // 6 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(21, 30), // (22,30): warning CS8601: Possible null reference assignment. // new CClass().P3 = t3; // 7, [DisallowNull] honored on TClass? Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(22, 30), // (35,30): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new COpen().P1 = t5; // 8 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(35, 30), // (36,31): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new CStruct().P5 = t5; // 9 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(36, 31) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var copen = (NamedTypeSymbol)m.GlobalNamespace.GetMember("COpen"); var copenAttributes = copen.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(copenAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.NullableContextAttribute(1)", "System.Runtime.CompilerServices.NullableAttribute(0)" }, copenAttributes); } var property = copen.GetMembers().OfType().Single(); var propertyAttributes = property.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.DisallowNullAttribute" }, propertyAttributes); } else { AssertEx.Empty(propertyAttributes); } var setter = property.SetMethod; var setterAttributes = setter.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(setterAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.CompilerGeneratedAttribute" }, setterAttributes); } var setterValueAttributes = setter.Parameters.Last().GetAttributes().Select(a => a.ToString()); Assert.Equal(FlowAnalysisAnnotations.DisallowNull, setter.Parameters.Last().FlowAnalysisAnnotations); if (isSource) { AssertEx.Empty(setterValueAttributes); } else { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.DisallowNullAttribute" }, setterValueAttributes); } } } [Fact] public void DisallowNull_Property_NullInitializer() { var source = @"using System.Diagnostics.CodeAnalysis; public class C { [DisallowNull]public string? P1 { get; set; } = null; } "; // Missing warning. Honor nullability attributes in method bodies https://github.com/dotnet/roslyn/issues/36039 var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void AllowNull_Parameter_NullDefaultValue() { var source = @"using System.Diagnostics.CodeAnalysis; public class C { void M([AllowNull] string p = null) { } } "; // Honor nullability attributes in optional parameters https://github.com/dotnet/roslyn/issues/36039 var comp = CreateNullableCompilation(new[] { AllowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (4,35): warning CS8625: Cannot convert null literal to non-nullable reference type. // void M([AllowNull] string p = null) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 35) ); } [Fact] public void Disallow_Property_OnVirtualProperty_OnlyOverridingGetter() { var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [DisallowNull] public virtual string? P { get { throw null!; } set { throw null!; } } public virtual string? P2 { get { throw null!; } set { throw null!; } } } public class C : Base { public override string? P { get { throw null!; } } [DisallowNull] public override string? P2 { get { throw null!; } } static void M(C c, Base b) { b.P = null; // 1 c.P = null; // 2 b.P2 = null; c.P2 = null; } }"; var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // b.P = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 15), // (16,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.P = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 15) ); } [Fact] public void Disallow_Indexer_OnVirtualIndexer_OnlyOverridingSetter() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [DisallowNull] public virtual string? this[int i] { get { throw null!; } set { throw null!; } } public virtual string? this[byte i] { get { throw null!; } set { throw null!; } } } public class C : Base { public override string? this[int it] { set { throw null!; } } [DisallowNull] public override string? this[byte i] { set { throw null!; } } static void M(C c, Base b) { b[(int)0] = null; // 1 c[(int)0] = null; b[(byte)0] = null; c[(byte)0] = null; // 2 } }"; var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,21): warning CS8625: Cannot convert null literal to non-nullable reference type. // b[(int)0] = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 21), // (19,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // c[(byte)0] = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 22) ); } [Fact] public void DisallowNull_Property_CompoundAssignment() { var source = @" using System.Diagnostics.CodeAnalysis; class C { [DisallowNull] C? Property { get; set; } = null!; public static C? operator+(C? one, C other) => throw null!; void M(C c) { Property += c; // 1 } } struct S { [DisallowNull] S? Property { get { throw null!; } set { throw null!; } } public static S? operator+(S? one, S other) => throw null!; void M(S s) { Property += s; // 2 } }"; var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition }); comp.VerifyDiagnostics( // (10,9): warning CS8601: Possible null reference assignment. // Property += c; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "Property += c").WithLocation(10, 9), // (20,9): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // Property += s; // 2 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "Property += s").WithLocation(20, 9) ); } [Fact] public void DisallowNull_Operator_CompoundAssignment() { var source = @" using System.Diagnostics.CodeAnalysis; class C { C? Property { get; set; } = null!; public static C? operator+([DisallowNull] C? one, C other) => throw null!; void M(C c) { Property += c; // 1 } } struct S { S? Property { get { throw null!; } set { throw null!; } } public static S? operator+([DisallowNull] S? one, S other) => throw null!; void M(S s) { Property += s; // 2 } }"; var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition }); comp.VerifyDiagnostics( // (10,9): warning CS8604: Possible null reference argument for parameter 'one' in 'C? C.operator +(C? one, C other)'. // Property += c; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "Property").WithArguments("one", "C? C.operator +(C? one, C other)").WithLocation(10, 9), // (20,9): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // Property += s; // 2 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "Property").WithLocation(20, 9) ); } [Fact] public void DisallowNull_Property_OnVirtualProperty() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [DisallowNull] public virtual string? P { get; set; } = null!; public virtual string? P2 { get; set; } = null!; } public class C : Base { public override string? P { get; set; } = null!; [DisallowNull] public override string? P2 { get; set; } = null!; static void M(C c, Base b) { b.P = null; // 1 c.P = null; b.P2 = null; c.P2 = null; // 2 } }"; var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition }); comp.VerifyDiagnostics( // (15,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // b.P = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 15), // (19,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.P2 = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 16) ); } [Fact] public void DisallowNull_Property_Cycle() { var source = @" namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = true)] public sealed class DisallowNullAttribute : Attribute { [DisallowNull, DisallowNull(1)] int Property { get; set; } public DisallowNullAttribute() { } public DisallowNullAttribute([DisallowNull] int i) { } } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics(); } [Fact] public void DisallowNull_Property_ExplicitSetter() { // Warn on misused nullability attributes (P2, P3, P4)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; public class COpen { [DisallowNull]public TOpen P1 { get { throw null!; } set { throw null!; } } } public class CClass where TClass : class { [DisallowNull]public TClass P2 { get { throw null!; } set { throw null!; } } [DisallowNull]public TClass? P3 { get { throw null!; } set { throw null!; } } } public class CStruct where TStruct : struct { [DisallowNull]public TStruct P4 { get { throw null!; } set { throw null!; } } [DisallowNull]public TStruct? P5 { get { throw null!; } set { throw null!; } } } class C { static void M1(T t1) { new COpen().P1 = t1; } static void M2(T t2) where T : class { new COpen().P1 = t2; new CClass().P2 = t2; new CClass().P3 = t2; t2 = null; // 1 new COpen().P1 = t2; // 2 new CClass().P2 = t2; // 3 new CClass().P3 = t2; // 4, [DisallowNull] honored on TClass? } static void M3(T? t3) where T : class { new COpen().P1 = t3; // 5 new CClass().P2 = t3; // 6 new CClass().P3 = t3; // 7, [DisallowNull] honored on TClass? if (t3 == null) return; new COpen().P1 = t3; new CClass().P2 = t3; new CClass().P3 = t3; } static void M4(T t4) where T : struct { new COpen().P1 = t4; new CStruct().P4 = t4; } static void M5(T? t5) where T : struct { new COpen().P1 = t5; // 8 new CStruct().P5 = t5; // 9 if (t5 == null) return; new COpen().P1 = t5; new CStruct().P5 = t5; } }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (27,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(27, 14), // (28,29): warning CS8601: Possible null reference assignment. // new COpen().P1 = t2; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(28, 29), // (29,30): warning CS8601: Possible null reference assignment. // new CClass().P2 = t2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(29, 30), // (30,30): warning CS8601: Possible null reference assignment. // new CClass().P3 = t2; // 4, [DisallowNull] honored on TClass? Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(30, 30), // (34,29): warning CS8601: Possible null reference assignment. // new COpen().P1 = t3; // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(34, 29), // (35,30): warning CS8601: Possible null reference assignment. // new CClass().P2 = t3; // 6 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(35, 30), // (36,30): warning CS8601: Possible null reference assignment. // new CClass().P3 = t3; // 7, [DisallowNull] honored on TClass? Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(36, 30), // (49,30): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new COpen().P1 = t5; // 8 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(49, 30), // (50,31): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new CStruct().P5 = t5; // 9 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(50, 31) ); } [Fact] public void DisallowNull_Property_OnSetter() { var source = @"using System.Diagnostics.CodeAnalysis; public class CClass where TClass : class { public TClass P2 { get; [DisallowNull] set; } = null!; public TClass? P3 { get; [DisallowNull] set; } = null; }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (4,30): error CS0592: Attribute 'DisallowNull' is not valid on this declaration type. It is only valid on 'property, indexer, field, parameter' declarations. // public TClass P2 { get; [DisallowNull] set; } = null!; Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "DisallowNull").WithArguments("DisallowNull", "property, indexer, field, parameter").WithLocation(4, 30), // (5,31): error CS0592: Attribute 'DisallowNull' is not valid on this declaration type. It is only valid on 'property, indexer, field, parameter' declarations. // public TClass? P3 { get; [DisallowNull] set; } = null; Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "DisallowNull").WithArguments("DisallowNull", "property, indexer, field, parameter").WithLocation(5, 31) ); } [Fact] public void DisallowNull_Property_OnGetter() { var source = @"using System.Diagnostics.CodeAnalysis; public class CClass where TClass : class { public TClass P2 { [DisallowNull] get; set; } = null!; public TClass? P3 { [DisallowNull] get; set; } = null; }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (4,25): error CS0592: Attribute 'DisallowNull' is not valid on this declaration type. It is only valid on 'property, indexer, field, parameter' declarations. // public TClass P2 { [DisallowNull] get; set; } = null!; Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "DisallowNull").WithArguments("DisallowNull", "property, indexer, field, parameter").WithLocation(4, 25), // (5,26): error CS0592: Attribute 'DisallowNull' is not valid on this declaration type. It is only valid on 'property, indexer, field, parameter' declarations. // public TClass? P3 { [DisallowNull] get; set; } = null; Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "DisallowNull").WithArguments("DisallowNull", "property, indexer, field, parameter").WithLocation(5, 26) ); } [Fact] public void DisallowNull_Property_NoGetter() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; public class COpen { [DisallowNull]public TOpen P1 { set { throw null!; } } [DisallowNull]public TOpen P2 => default!; }"; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void DisallowNull_Indexer() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [DisallowNull]public TOpen this[int i] { set => throw null!; } } public class CClass where TClass : class? { [DisallowNull]public TClass this[int i] { set => throw null!; } } public class CClass2 where TClass : class { [DisallowNull]public TClass? this[int i] { set => throw null!; } } public class CStruct where TStruct : struct { [DisallowNull]public TStruct this[int i] { set => throw null!; } } public class CStruct2 where TStruct : struct { [DisallowNull]public TStruct? this[int i] { set => throw null!; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class C { static void M1(T t1) { new COpen()[0] = t1; } static void M2(T t2) where T : class { new COpen()[0] = t2; new CClass()[0] = t2; new CClass2()[0] = t2; t2 = null; // 1 new COpen()[0] = t2; // 2 new CClass()[0] = t2; // 3 new CClass2()[0] = t2; // 4, [DisallowNull] honored on TClass? } static void M3(T? t3) where T : class { new COpen()[0] = t3; // 5 new CClass()[0] = t3; // 6 new CClass2()[0] = t3; // 7, [DisallowNull] honored on TClass? if (t3 == null) return; new COpen()[0] = t3; new CClass()[0] = t3; new CClass2()[0] = t3; } static void M4(T t4) where T : struct { new COpen()[0] = t4; new CStruct()[0] = t4; } static void M5(T? t5) where T : struct { new COpen()[0] = t5; // 8 new CStruct2()[0] = t5; // 9 if (t5 == null) return; new COpen()[0] = t5; new CStruct2()[0] = t5; } }"; var expected = new[] { // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 14), // (14,29): warning CS8601: Possible null reference assignment. // new COpen()[0] = t2; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(14, 29), // (15,30): warning CS8601: Possible null reference assignment. // new CClass()[0] = t2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(15, 30), // (16,31): warning CS8601: Possible null reference assignment. // new CClass2()[0] = t2; // 4, [DisallowNull] honored on TClass? Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(16, 31), // (20,29): warning CS8601: Possible null reference assignment. // new COpen()[0] = t3; // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(20, 29), // (21,30): warning CS8601: Possible null reference assignment. // new CClass()[0] = t3; // 6 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(21, 30), // (22,31): warning CS8601: Possible null reference assignment. // new CClass2()[0] = t3; // 7, [DisallowNull] honored on TClass? Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t3").WithLocation(22, 31), // (35,30): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new COpen()[0] = t5; // 8 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(35, 30), // (36,32): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new CStruct2()[0] = t5; // 9 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "t5").WithLocation(36, 32) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void DisallowNull_Indexer_OtherParameters_String() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class C { public string? this[[DisallowNull] string? s] { set => throw null!; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new C()[s] = s; // 1 new C()[s2] = s; } }"; var expected = new[] { // (6,17): warning CS8604: Possible null reference argument for parameter 's' in 'string? C.this[string? s]'. // new C()[s] = s; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "s").WithArguments("s", "string? C.this[string? s]").WithLocation(6, 17) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void DisallowNull_Indexer_OtherParameters_NullableInt() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class C { public int? this[[DisallowNull] int? s] { set => throw null!; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(int? i, int i2) { new C()[i] = i; // 1 new C()[i2] = i; } }"; var expected = new[] { // (6,17): warning CS8607: A possible null value may not be passed to a target marked with the [DisallowNull] attribute // new C()[i] = i; // 1 Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "i").WithLocation(6, 17) }; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(expected); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(expected); } [Fact] public void DisallowNull_Indexer_OtherParameters_OverridingGetter() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual string this[[DisallowNull] string? s] { get => throw null!; } } public class C : Base { public override string this[string? s] { get => throw null!; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new C()[s].ToString(); new C()[s2].ToString(); } }"; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(); } [Fact, WorkItem(36630, "https://github.com/dotnet/roslyn/issues/36630")] public void DisallowNull_Indexer_OtherParameters_OverridingGetterOnly() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual string this[[DisallowNull] string? s] { get => throw null!; set => throw null!; } } public class C : Base { public override string this[string? s] { set => throw null!; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new C()[s].ToString(); // 1 new C()[s2].ToString(); } }"; // Should report a warning for explicit parameter on getter https://github.com/dotnet/roslyn/issues/36630 var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(); } [Fact] public void DisallowNull_Indexer_OtherParameters_OverridingSetterOnly() { var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual string this[[DisallowNull] string? s] { get => throw null!; set => throw null!; } } public class C : Base { public override string this[string? s] { get => throw null!; } } "; var lib = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, lib_cs }); var source = @" class D { static void M1(string? s, string s2) { new C()[s].ToString(); new C()[s2].ToString(); } }"; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, DisallowNullAttributeDefinition }); comp2.VerifyDiagnostics(); } [Fact] public void MaybeNullWhenFalse_WithNotNullWhenTrue() { var source = @"using System.Diagnostics.CodeAnalysis; internal class C where T : class? { public bool TryGetTarget([MaybeNullWhen(false), NotNullWhen(true)] out T target) => throw null!; public string Method(C wr) { if (!wr.TryGetTarget(out string? s)) { s = """"; } return s; } }"; var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, NotNullWhenAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void MaybeNull_WithNotNull() { var source = @"using System.Diagnostics.CodeAnalysis; internal class C where T : class? { public bool F([MaybeNull, NotNull] out T target) => throw null!; [return: MaybeNull, NotNull] public T F2() => throw null!; public string Method(C wr) { if (!wr.F(out string? s)) { s = """"; } return s; // 1 } public string Method2(C wr, bool b) { var s = wr.F2(); if (b) return s; // 2 s = null; throw null!; } }"; // MaybeNull wins over NotNull var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, NotNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (13,16): warning CS8603: Possible null reference return. // return s; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(13, 16), // (19,20): warning CS8603: Possible null reference return. // return s; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(19, 20) ); } [Fact] public void MaybeNull_WithNotNullWhenTrue() { var source = @"using System.Diagnostics.CodeAnalysis; internal class C where T : class? { public bool TryGetTarget([MaybeNull, NotNullWhen(true)] out T target) => throw null!; public string Method(C wr) { if (!wr.TryGetTarget(out string? s)) { s = """"; } return s; // 1 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, NotNullWhenAttributeDefinition, source }); comp.VerifyDiagnostics( // (11,16): warning CS8603: Possible null reference return. // return s; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(11, 16) ); } [Fact] public void MaybeNull_ReturnValue_01() { // Warn on misused nullability attributes (F2, F3, F4)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: MaybeNull] static T F1(T t) => t; [return: MaybeNull] static T F2(T t) where T : class => t; [return: MaybeNull] static T? F3(T t) where T : class => t; [return: MaybeNull] static T F4(T t) where T : struct => t; [return: MaybeNull] static T? F5(T? t) where T : struct => t; static void M1(T t1) { F1(t1).ToString(); // 1 } static void M2(T t2) where T : class { F1(t2).ToString(); // 2 F2(t2).ToString(); // 3 F3(t2).ToString(); // 4 t2 = null; // 5 F1(t2).ToString(); // 6 F2(t2).ToString(); // 7 F3(t2).ToString(); // 8 } static void M3(T? t3) where T : class { F1(t3).ToString(); // 9 F2(t3).ToString(); // 10 F3(t3).ToString(); // 11 if (t3 == null) return; F1(t3).ToString(); // 12 F2(t3).ToString(); // 13 F3(t3).ToString(); // 14 } static void M4(T t4) where T : struct { F1(t4).ToString(); F4(t4).ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5).Value; // 15 _ = F5(t5).Value; // 16 if (t5 == null) return; _ = F1(t5).Value; // 17 _ = F5(t5).Value; // 18 } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // F1(t1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t1)").WithLocation(11, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // F1(t2).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t2)").WithLocation(15, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // F2(t2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t2)").WithLocation(16, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // F3(t2).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t2)").WithLocation(17, 9), // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,9): warning CS8602: Dereference of a possibly null reference. // F1(t2).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t2)").WithLocation(19, 9), // (20,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(20, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // F2(t2).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t2)").WithLocation(20, 9), // (21,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t2).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T)", "T", "T?").WithLocation(21, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // F3(t2).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t2)").WithLocation(21, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // F1(t3).ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t3)").WithLocation(25, 9), // (26,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3).ToString(); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(26, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // F2(t3).ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t3)").WithLocation(26, 9), // (27,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t3).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T)", "T", "T?").WithLocation(27, 9), // (27,9): warning CS8602: Dereference of a possibly null reference. // F3(t3).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t3)").WithLocation(27, 9), // (29,9): warning CS8602: Dereference of a possibly null reference. // F1(t3).ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t3)").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // F2(t3).ToString(); // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t3)").WithLocation(30, 9), // (31,9): warning CS8602: Dereference of a possibly null reference. // F3(t3).ToString(); // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t3)").WithLocation(31, 9), // (40,13): warning CS8629: Nullable value type may be null. // _ = F1(t5).Value; // 15 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F1(t5)").WithLocation(40, 13), // (41,13): warning CS8629: Nullable value type may be null. // _ = F5(t5).Value; // 16 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F5(t5)").WithLocation(41, 13), // (43,13): warning CS8629: Nullable value type may be null. // _ = F1(t5).Value; // 17 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F1(t5)").WithLocation(43, 13), // (44,13): warning CS8629: Nullable value type may be null. // _ = F5(t5).Value; // 18 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F5(t5)").WithLocation(44, 13)); } [Fact] public void MaybeNull_ReturnValue_02() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: MaybeNull] static T F1(T t) => t; [return: MaybeNull] static T F2(T t) where T : class => t; [return: MaybeNull] static T? F3(T t) where T : class => t; [return: MaybeNull] static T F4(T t) where T : struct => t; [return: MaybeNull] static T? F5(T? t) where T : struct => t; static void M1(T t1) { F1(t1).ToString(); // 1 } static void M2(T t2) where T : class { F1(t2).ToString(); // 2 F2(t2).ToString(); // 3 F3(t2).ToString(); // 4 t2 = null; // 5 F1(t2).ToString(); // 6 F2(t2).ToString(); // 7 F3(t2).ToString(); // 8 } static void M3(T? t3) where T : class { F1(t3).ToString(); // 9 F2(t3).ToString(); // 10 F3(t3).ToString(); // 11 if (t3 == null) return; F1(t3).ToString(); // 12 F2(t3).ToString(); // 13 F3(t3).ToString(); // 14 } static void M4(T t4) where T : struct { F1(t4).ToString(); F4(t4).ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5).Value; // 15 _ = F5(t5).Value; // 16 if (t5 == null) return; _ = F1(t5).Value; // 17 _ = F5(t5).Value; // 18 } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // F1(t1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t1)").WithLocation(11, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // F1(t2).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t2)").WithLocation(15, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // F2(t2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t2)").WithLocation(16, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // F3(t2).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t2)").WithLocation(17, 9), // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,9): warning CS8602: Dereference of a possibly null reference. // F1(t2).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t2)").WithLocation(19, 9), // (19,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F1(T t)'. // F1(t2).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T Program.F1(T t)").WithLocation(19, 15), // (20,9): warning CS8602: Dereference of a possibly null reference. // F2(t2).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t2)").WithLocation(20, 9), // (20,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F2(T t)'. // F2(t2).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T Program.F2(T t)").WithLocation(20, 15), // (21,9): warning CS8602: Dereference of a possibly null reference. // F3(t2).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t2)").WithLocation(21, 9), // (21,15): warning CS8604: Possible null reference argument for parameter 't' in 'T? Program.F3(T t)'. // F3(t2).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T? Program.F3(T t)").WithLocation(21, 15), // (25,9): warning CS8602: Dereference of a possibly null reference. // F1(t3).ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t3)").WithLocation(25, 9), // (25,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F1(T t)'. // F1(t3).ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T Program.F1(T t)").WithLocation(25, 15), // (26,9): warning CS8602: Dereference of a possibly null reference. // F2(t3).ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t3)").WithLocation(26, 9), // (26,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F2(T t)'. // F2(t3).ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T Program.F2(T t)").WithLocation(26, 15), // (27,9): warning CS8602: Dereference of a possibly null reference. // F3(t3).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t3)").WithLocation(27, 9), // (27,15): warning CS8604: Possible null reference argument for parameter 't' in 'T? Program.F3(T t)'. // F3(t3).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T? Program.F3(T t)").WithLocation(27, 15), // (29,9): warning CS8602: Dereference of a possibly null reference. // F1(t3).ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t3)").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // F2(t3).ToString(); // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t3)").WithLocation(30, 9), // (31,9): warning CS8602: Dereference of a possibly null reference. // F3(t3).ToString(); // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t3)").WithLocation(31, 9), // (40,13): warning CS8629: Nullable value type may be null. // _ = F1(t5).Value; // 15 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F1(t5)").WithLocation(40, 13), // (41,13): warning CS8629: Nullable value type may be null. // _ = F5(t5).Value; // 16 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F5(t5)").WithLocation(41, 13), // (43,13): warning CS8629: Nullable value type may be null. // _ = F1(t5).Value; // 17 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F1(t5)").WithLocation(43, 13), // (44,13): warning CS8629: Nullable value type may be null. // _ = F5(t5).Value; // 18 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F5(t5)").WithLocation(44, 13)); } [Fact] public void MaybeNull_ReturnValue_02_WithNotNull() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: MaybeNull, NotNull] static T F1(T t) => t; [return: MaybeNull, NotNull] static T F2(T t) where T : class => t; [return: MaybeNull, NotNull] static T? F3(T t) where T : class => t; [return: MaybeNull, NotNull] static T F4(T t) where T : struct => t; [return: MaybeNull, NotNull] static T? F5(T? t) where T : struct => t; static void M1(T t1) { F1(t1).ToString(); // 1 } static void M2(T t2) where T : class { F1(t2).ToString(); // 2 F2(t2).ToString(); // 3 F3(t2).ToString(); // 4 t2 = null; // 5 F1(t2).ToString(); // 6 F2(t2).ToString(); // 7 F3(t2).ToString(); // 8 } static void M3(T? t3) where T : class { F1(t3).ToString(); // 9 F2(t3).ToString(); // 10 F3(t3).ToString(); // 11 if (t3 == null) return; F1(t3).ToString(); // 12 F2(t3).ToString(); // 13 F3(t3).ToString(); // 14 } static void M4(T t4) where T : struct { F1(t4).ToString(); F4(t4).ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5).Value; // 15 _ = F5(t5).Value; // 16 if (t5 == null) return; _ = F1(t5).Value; // 17 _ = F5(t5).Value; // 18 } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // F1(t1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t1)").WithLocation(11, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // F1(t2).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t2)").WithLocation(15, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // F2(t2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t2)").WithLocation(16, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // F3(t2).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t2)").WithLocation(17, 9), // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,9): warning CS8602: Dereference of a possibly null reference. // F1(t2).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t2)").WithLocation(19, 9), // (19,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F1(T t)'. // F1(t2).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T Program.F1(T t)").WithLocation(19, 15), // (20,9): warning CS8602: Dereference of a possibly null reference. // F2(t2).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t2)").WithLocation(20, 9), // (20,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F2(T t)'. // F2(t2).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T Program.F2(T t)").WithLocation(20, 15), // (21,9): warning CS8602: Dereference of a possibly null reference. // F3(t2).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t2)").WithLocation(21, 9), // (21,15): warning CS8604: Possible null reference argument for parameter 't' in 'T? Program.F3(T t)'. // F3(t2).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T? Program.F3(T t)").WithLocation(21, 15), // (25,9): warning CS8602: Dereference of a possibly null reference. // F1(t3).ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t3)").WithLocation(25, 9), // (25,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F1(T t)'. // F1(t3).ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T Program.F1(T t)").WithLocation(25, 15), // (26,9): warning CS8602: Dereference of a possibly null reference. // F2(t3).ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t3)").WithLocation(26, 9), // (26,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F2(T t)'. // F2(t3).ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T Program.F2(T t)").WithLocation(26, 15), // (27,9): warning CS8602: Dereference of a possibly null reference. // F3(t3).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t3)").WithLocation(27, 9), // (27,15): warning CS8604: Possible null reference argument for parameter 't' in 'T? Program.F3(T t)'. // F3(t3).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T? Program.F3(T t)").WithLocation(27, 15), // (29,9): warning CS8602: Dereference of a possibly null reference. // F1(t3).ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(t3)").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // F2(t3).ToString(); // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(t3)").WithLocation(30, 9), // (31,9): warning CS8602: Dereference of a possibly null reference. // F3(t3).ToString(); // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F3(t3)").WithLocation(31, 9), // (40,13): warning CS8629: Nullable value type may be null. // _ = F1(t5).Value; // 15 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F1(t5)").WithLocation(40, 13), // (41,13): warning CS8629: Nullable value type may be null. // _ = F5(t5).Value; // 16 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F5(t5)").WithLocation(41, 13), // (43,13): warning CS8629: Nullable value type may be null. // _ = F1(t5).Value; // 17 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F1(t5)").WithLocation(43, 13), // (44,13): warning CS8629: Nullable value type may be null. // _ = F5(t5).Value; // 18 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F5(t5)").WithLocation(44, 13)); } [Fact] public void MaybeNull_ReturnValue_03() { // Warn on misused nullability attributes (F1, F2)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: MaybeNull] static string F1() => string.Empty; [return: MaybeNull] static string? F2() => string.Empty; static void M() { F1().ToString(); // 1 F2().ToString(); // 2 } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // F1().ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1()").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // F2().ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2()").WithLocation(9, 9)); } [Fact] public void MaybeNull_ReturnValue_04() { // Warn on misused nullability attributes (F1, F2)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: MaybeNull] static int F1() => 1; [return: MaybeNull] static int? F2() => 2; static void M() { F1().ToString(); _ = F2().Value; // 1 } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8629: Nullable value type may be null. // _ = F2().Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "F2()").WithLocation(9, 13)); } [Fact] public void MaybeNull_ReturnValue_05() { // Warn on misused nullability attributes (F2)? https://github.com/dotnet/roslyn/issues/36073 var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static T F1(T t) where T : class => t; [return: MaybeNull] public static T F2(T t) where T : class => t; }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x).ToString(); // 2, 3 F1(y).ToString(); F2(x).ToString(); // 4, 5 F2(y).ToString(); // 6 } }"; comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(x).ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T)", "T", "object?").WithLocation(7, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // F1(x).ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x)").WithLocation(7, 9), // (9,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x).ToString(); // 4, 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T)", "T", "object?").WithLocation(9, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // F2(x).ToString(); // 4, 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(x)").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // F2(y).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(y)").WithLocation(10, 9) ); } [Fact] public void MaybeNull_ReturnValue_05_Unconstrained() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static T F1(T t) => t; [return: MaybeNull] public static T F2(T t) => t; }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x).ToString(); // 2 F1(y).ToString(); F2(x).ToString(); // 3 F2(y).ToString(); // 4 } }"; comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8602: Dereference of a possibly null reference. // F1(x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x)").WithLocation(7, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // F2(x).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(x)").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // F2(y).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(y)").WithLocation(10, 9) ); } [Fact] public void MaybeNull_ReturnValue_06() { var source = @"using System.Diagnostics.CodeAnalysis; class C { [return: MaybeNull] internal static T F() => throw null!; } class Program { static void M() where U : class where V : struct { C.F().ToString(); // 1 C.F().ToString(); // 2 C.F().ToString(); // 3 C.F().ToString(); _ = C.F().Value; // 4 C.F().ToString(); // 5 C.F().ToString(); // 6 C.F().ToString(); _ = C.F().Value; // 7 } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // C.F().ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F()").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // C.F().ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F()").WithLocation(13, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // C.F().ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F()").WithLocation(14, 9), // (16,13): warning CS8629: Nullable value type may be null. // _ = C.F().Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "C.F()").WithLocation(16, 13), // (17,9): warning CS8602: Dereference of a possibly null reference. // C.F().ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F()").WithLocation(17, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // C.F().ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F()").WithLocation(18, 9), // (20,13): warning CS8629: Nullable value type may be null. // _ = C.F().Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "C.F()").WithLocation(20, 13)); } [Fact] public void MaybeNull_InOrByValParameter() { var c = CreateCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; public class C { public void Main(string s1, string s2) { _ = M(s1) ? s1.ToString() // 1 : s1.ToString(); // 2 _ = M(s2) ? s2.ToString() // 3 : s2.ToString(); // 4 } public static bool M([MaybeNull] in string s) => throw null!; public static bool M2([MaybeNull] string s) => throw null!; } ", MaybeNullAttributeDefinition }, options: WithNonNullTypesTrue()); // Warn on misused nullability attributes (warn on parameters of M and M2)? https://github.com/dotnet/roslyn/issues/36073 c.VerifyDiagnostics( // (8,15): warning CS8602: Dereference of a possibly null reference. // ? s1.ToString() // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(8, 15), // (9,15): warning CS8602: Dereference of a possibly null reference. // : s1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(9, 15), // (12,15): warning CS8602: Dereference of a possibly null reference. // ? s2.ToString() // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 15), // (13,15): warning CS8602: Dereference of a possibly null reference. // : s2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(13, 15) ); } [Fact] public void MaybeNull_OutParameter_01() { // Warn on misused nullability attributes (F2, F3, F4 and probably F5)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1(T t, [MaybeNull]out T t2) { t2 = t; } static void F2(T t, [MaybeNull]out T t2) where T : class { t2 = t; } static void F3(T t, [MaybeNull]out T? t2) where T : class { t2 = t; } static void F4(T t, [MaybeNull]out T t2) where T : struct { t2 = t; } static void F5(T? t, [MaybeNull]out T? t2) where T : struct { t2 = t; } static void M1(T t1) { F1(t1, out var s2); s2.ToString(); // 1 } static void M2(T t2) where T : class { F1(t2, out var s3); s3.ToString(); // 2 F2(t2, out var s4); s4.ToString(); // 3 F3(t2, out var s5); s5.ToString(); // 4 t2 = null; // 5 F1(t2, out var s6); s6.ToString(); // 6 F2(t2, out var s7); // 7 s7.ToString(); // 8 F3(t2, out var s8); // 9 s8.ToString(); // 10 } static void M3(T? t3) where T : class { F1(t3, out var s9); s9.ToString(); // 11 F2(t3, out var s10); // 12 s10.ToString(); // 13 F3(t3, out var s11); // 14 s11.ToString(); // 15 if (t3 == null) return; F1(t3, out var s12); s12.ToString(); // 16 F2(t3, out var s13); s13.ToString(); // 17 F3(t3, out var s14); s14.ToString(); // 18 } static void M4(T t4) where T : struct { F1(t4, out var s15); s15.ToString(); F4(t4, out var s16); s16.ToString(); } static void M5(T? t5) where T : struct { F1(t5, out var s17); _ = s17.Value; // 19 F5(t5, out var s18); _ = s18.Value; // 20 if (t5 == null) return; F1(t5, out var s19); _ = s19.Value; // 21 F5(t5, out var s20); _ = s20.Value; // 22 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // s3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(17, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(20, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // s5.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(23, 9), // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(25, 14), // (27,9): warning CS8602: Dereference of a possibly null reference. // s6.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s6").WithLocation(27, 9), // (29,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2, out var s7); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // s7.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s7").WithLocation(30, 9), // (32,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t2, out var s8); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(32, 9), // (33,9): warning CS8602: Dereference of a possibly null reference. // s8.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s8").WithLocation(33, 9), // (38,9): warning CS8602: Dereference of a possibly null reference. // s9.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s9").WithLocation(38, 9), // (40,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3, out var s10); // 12 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(40, 9), // (41,9): warning CS8602: Dereference of a possibly null reference. // s10.ToString(); // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s10").WithLocation(41, 9), // (43,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t3, out var s11); // 14 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(43, 9), // (44,9): warning CS8602: Dereference of a possibly null reference. // s11.ToString(); // 15 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s11").WithLocation(44, 9), // (48,9): warning CS8602: Dereference of a possibly null reference. // s12.ToString(); // 16 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s12").WithLocation(48, 9), // (51,9): warning CS8602: Dereference of a possibly null reference. // s13.ToString(); // 17 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s13").WithLocation(51, 9), // (54,9): warning CS8602: Dereference of a possibly null reference. // s14.ToString(); // 18 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s14").WithLocation(54, 9), // (67,13): warning CS8629: Nullable value type may be null. // _ = s17.Value; // 19 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s17").WithLocation(67, 13), // (70,13): warning CS8629: Nullable value type may be null. // _ = s18.Value; // 20 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s18").WithLocation(70, 13), // (74,13): warning CS8629: Nullable value type may be null. // _ = s19.Value; // 21 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s19").WithLocation(74, 13), // (77,13): warning CS8629: Nullable value type may be null. // _ = s20.Value; // 22 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s20").WithLocation(77, 13) ); } [Fact] public void MaybeNull_OutParameter_02() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1(T t, [MaybeNull]out T t2) => throw null!; static void F2(T t, [MaybeNull]out T t2) where T : class => throw null!; static void F3(T t, [MaybeNull]out T? t2) where T : class => throw null!; static void F4(T t, [MaybeNull]out T t2) where T : struct => throw null!; static void F5(T? t, [MaybeNull]out T? t2) where T : struct => throw null!; static void M1(T t1) { F1(t1, out var s1); s1.ToString(); // 1 } static void M2(T t2) where T : class { F1(t2, out var s2); s2.ToString(); // 2 F2(t2, out var s3); s3.ToString(); // 3 F3(t2, out var s4); s4.ToString(); // 4 t2 = null; // 5 F1(t2, out var s5); // 6 s5.ToString(); // 6B F2(t2, out var s6); // 7 s6.ToString(); // 7B F3(t2, out var s7); // 8 s7.ToString(); // 8B } static void M3(T? t3) where T : class { F1(t3, out var s8); // 9 s8.ToString(); // 9B F2(t3, out var s9); // 10 s9.ToString(); // 10B F3(t3, out var s10); // 11 s10.ToString(); // 11B if (t3 == null) return; F1(t3, out var s11); s11.ToString(); // 12 F2(t3, out var s12); s12.ToString(); // 13 F3(t3, out var s13); s13.ToString(); // 14 } static void M4(T t4) where T : struct { F1(t4, out var s14); s14.ToString(); F4(t4, out var s15); s15.ToString(); } static void M5(T? t5) where T : struct { F1(t5, out var s16); _ = s16.Value; // 15 F5(t5, out var s17); _ = s17.Value; // 16 if (t5 == null) return; F1(t5, out var s18); _ = s18.Value; // 17 F5(t5, out var s19); _ = s19.Value; // 18 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // s1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(12, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(17, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // s3.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(20, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(23, 9), // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(25, 14), // (26,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T t, out T t2)'. // F1(t2, out var s5); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F1(T t, out T t2)").WithLocation(26, 15), // (27,9): warning CS8602: Dereference of a possibly null reference. // s5.ToString(); // 6B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(27, 9), // (29,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T t, out T t2)'. // F2(t2, out var s6); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F2(T t, out T t2)").WithLocation(29, 15), // (30,9): warning CS8602: Dereference of a possibly null reference. // s6.ToString(); // 7B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s6").WithLocation(30, 9), // (32,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T t, out T? t2)'. // F3(t2, out var s7); // 8 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "void Program.F3(T t, out T? t2)").WithLocation(32, 15), // (33,9): warning CS8602: Dereference of a possibly null reference. // s7.ToString(); // 8B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s7").WithLocation(33, 9), // (37,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F1(T t, out T t2)'. // F1(t3, out var s8); // 9 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F1(T t, out T t2)").WithLocation(37, 15), // (38,9): warning CS8602: Dereference of a possibly null reference. // s8.ToString(); // 9B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s8").WithLocation(38, 9), // (40,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F2(T t, out T t2)'. // F2(t3, out var s9); // 10 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F2(T t, out T t2)").WithLocation(40, 15), // (41,9): warning CS8602: Dereference of a possibly null reference. // s9.ToString(); // 10B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s9").WithLocation(41, 9), // (43,15): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.F3(T t, out T? t2)'. // F3(t3, out var s10); // 11 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "void Program.F3(T t, out T? t2)").WithLocation(43, 15), // (44,9): warning CS8602: Dereference of a possibly null reference. // s10.ToString(); // 11B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s10").WithLocation(44, 9), // (48,9): warning CS8602: Dereference of a possibly null reference. // s11.ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s11").WithLocation(48, 9), // (51,9): warning CS8602: Dereference of a possibly null reference. // s12.ToString(); // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s12").WithLocation(51, 9), // (54,9): warning CS8602: Dereference of a possibly null reference. // s13.ToString(); // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s13").WithLocation(54, 9), // (67,13): warning CS8629: Nullable value type may be null. // _ = s16.Value; // 15 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s16").WithLocation(67, 13), // (70,13): warning CS8629: Nullable value type may be null. // _ = s17.Value; // 16 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s17").WithLocation(70, 13), // (74,13): warning CS8629: Nullable value type may be null. // _ = s18.Value; // 17 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s18").WithLocation(74, 13), // (77,13): warning CS8629: Nullable value type may be null. // _ = s19.Value; // 18 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s19").WithLocation(77, 13) ); } [Fact] public void MaybeNull_OutParameter_03() { // Warn on misused nullability attributes (F1, F2)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([MaybeNull]out string t) => throw null!; static void F2([MaybeNull]out string? t) => throw null!; static void M() { F1(out var t1); t1.ToString(); // 1 F2(out var t2); t2.ToString(); // 2 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // t1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(9, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // t2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(12, 9) ); } [Fact] public void MaybeNull_OutParameter_04() { // Warn on misused nullability attributes (F1, F2)? https://github.com/dotnet/roslyn/issues/36073 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([MaybeNull]out int i) => throw null!; static void F2([MaybeNull]out int? i) => throw null!; static void M() { F1(out var i1); i1.ToString(); F2(out var i2); _ = i2.Value; // 1 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (12,13): warning CS8629: Nullable value type may be null. // _ = i2.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "i2").WithLocation(12, 13) ); } [Fact] public void MaybeNull_OutParameter_05() { // Warn on misused nullability attributes (F2)? https://github.com/dotnet/roslyn/issues/36073 var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static void F1(T t, out T t2) where T : class => throw null!; public static void F2(T t, [MaybeNull]out T t2) where T : class => throw null!; }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source0 }); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x, out var o1); // 2 o1.ToString(); // 2B F1(y, out var o2); o2.ToString(); F2(x, out var o3); // 3 o3.ToString(); // 3B F2(y, out var o4); o4.ToString(); // 4 } }"; comp = CreateNullableCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T, out T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(x, out var o1); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T, out T)", "T", "object?").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // o1.ToString(); // 2B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o1").WithLocation(8, 9), // (13,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T, out T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x, out var o3); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T, out T)", "T", "object?").WithLocation(13, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // o3.ToString(); // 3B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o3").WithLocation(14, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // o4.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o4").WithLocation(17, 9) ); } [Fact] public void MaybeNull_OutParameter_05_Unconstrained() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static void F2(T t, [MaybeNull]out T t2) => throw null!; }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source0 }); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F2(x, out var o3); o3.ToString(); // 2 F2(y, out var o4); o4.ToString(); // 3 } }"; comp = CreateNullableCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (9,9): warning CS8602: Dereference of a possibly null reference. // o3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o3").WithLocation(9, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // o4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o4").WithLocation(12, 9) ); } [Fact] public void MaybeNull_OutParameter_06() { var source = @"using System.Diagnostics.CodeAnalysis; class C { internal static void F([MaybeNull]out T t) => throw null!; } class Program { static void M() where U : class where V : struct { C.F(out var o1); o1.ToString(); // 1 C.F(out var o2); o2.ToString(); // 2 C.F(out var o3); o3.ToString(); // 3 C.F(out var o4); o4.ToString(); C.F(out var o5); _ = o5.Value; // 4 C.F(out var o6); o6.ToString(); // 5 C.F(out var o7); o7.ToString(); // 6 C.F(out var o8); o8.ToString(); C.F(out var o9); _ = o9.Value; // 7 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // o1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o1").WithLocation(13, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // o2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o2").WithLocation(16, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // o3.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o3").WithLocation(19, 9), // (25,13): warning CS8629: Nullable value type may be null. // _ = o5.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "o5").WithLocation(25, 13), // (28,9): warning CS8602: Dereference of a possibly null reference. // o6.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o6").WithLocation(28, 9), // (31,9): warning CS8602: Dereference of a possibly null reference. // o7.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o7").WithLocation(31, 9), // (37,13): warning CS8629: Nullable value type may be null. // _ = o9.Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "o9").WithLocation(37, 13) ); } [Fact] public void MaybeNull_RefParameter_01() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1(T t, [MaybeNull]ref T t2) { t2 = t; } static void F2(T t, [MaybeNull]ref T t2) where T : class { t2 = t; } static void F3(T t, [MaybeNull]ref T? t2) where T : class { t2 = t; } static void F4(T t, [MaybeNull]ref T t2) where T : struct { t2 = t; } static void F5(T? t, [MaybeNull]ref T? t2) where T : struct { t2 = t; } static void M1(T t1) { T s2 = default!; F1(t1, ref s2); s2.ToString(); // 1 } static void M2(T t2) where T : class { T? s3 = default!; F1(t2, ref s3); s3.ToString(); // 2 T s4 = default!; F2(t2, ref s4); // 3 s4.ToString(); // 4 T s4b = default!; F2(t2, ref s4b!); // suppression applies after MaybeNull s4b.ToString(); T? s5 = default!; F3(t2, ref s5); s5.ToString(); // 5 t2 = null; // 6 T? s6 = default!; F1(t2, ref s6); s6.ToString(); // 7 T? s7 = default!; F2(t2, ref s7); // 8 s7.ToString(); // 9 T? s8 = default!; F3(t2, ref s8); // 10 s8.ToString(); // 11 } static void M3(T? t3) where T : class { T? s9 = default!; F1(t3, ref s9); s9.ToString(); // 12 T s10 = default!; F2(t3, ref s10); // 13, 14 s10.ToString(); // 15 T? s11 = default!; F3(t3, ref s11); // 16 s11.ToString(); // 17 if (t3 == null) return; T s12 = default!; F1(t3, ref s12); // 18 s12.ToString(); // 19 T s13 = default!; F2(t3, ref s13); // 20 s13.ToString(); // 21 T? s14 = default!; F3(t3, ref s14); s14.ToString(); // 22 } static void M4(T t4) where T : struct { T s15 = default; F1(t4, ref s15); s15.ToString(); T s16 = default; F4(t4, ref s16); s16.ToString(); } static void M5(T? t5) where T : struct { T s17 = default!; F1(t5, ref s17); // 23 _ = s17.Value; // 24 T s18 = default!; F5(t5, ref s18); // 25 _ = s18.Value; // 26 if (t5 == null) return; T s19 = default!; F1(t5, ref s19); // 27 _ = s19.Value; // 28 T s20 = default!; F5(t5, ref s20); // 29 _ = s20.Value; // 30 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(13, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // s3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(19, 9), // (22,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // F2(t2, ref s4); // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s4").WithLocation(22, 20), // (23,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(23, 9), // (31,9): warning CS8602: Dereference of a possibly null reference. // s5.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s5").WithLocation(31, 9), // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(33, 14), // (36,9): warning CS8602: Dereference of a possibly null reference. // s6.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s6").WithLocation(36, 9), // (39,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, ref T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2, ref s7); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, ref T)", "T", "T?").WithLocation(39, 9), // (40,9): warning CS8602: Dereference of a possibly null reference. // s7.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s7").WithLocation(40, 9), // (43,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, ref T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t2, ref s8); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, ref T?)", "T", "T?").WithLocation(43, 9), // (44,9): warning CS8602: Dereference of a possibly null reference. // s8.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s8").WithLocation(44, 9), // (50,9): warning CS8602: Dereference of a possibly null reference. // s9.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s9").WithLocation(50, 9), // (53,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, ref T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3, ref s10); // 12, 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, ref T)", "T", "T?").WithLocation(53, 9), // (53,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // F2(t3, ref s10); // 12, 13 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s10").WithLocation(53, 20), // (54,9): warning CS8602: Dereference of a possibly null reference. // s10.ToString(); // 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s10").WithLocation(54, 9), // (57,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, ref T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t3, ref s11); // 15 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, ref T?)", "T", "T?").WithLocation(57, 9), // (58,9): warning CS8602: Dereference of a possibly null reference. // s11.ToString(); // 16 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s11").WithLocation(58, 9), // (62,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // F1(t3, ref s12); // 17 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s12").WithLocation(62, 20), // (63,9): warning CS8602: Dereference of a possibly null reference. // s12.ToString(); // 18 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s12").WithLocation(63, 9), // (66,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // F2(t3, ref s13); // 19 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s13").WithLocation(66, 20), // (67,9): warning CS8602: Dereference of a possibly null reference. // s13.ToString(); // 20 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s13").WithLocation(67, 9), // (71,9): warning CS8602: Dereference of a possibly null reference. // s14.ToString(); // 21 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s14").WithLocation(71, 9), // (86,9): error CS0411: The type arguments for method 'Program.F1(T, ref T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // F1(t5, ref s17); // 22 Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F1").WithArguments("Program.F1(T, ref T)").WithLocation(86, 9), // (87,17): error CS1061: 'T' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) // _ = s17.Value; // 23 Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Value").WithArguments("T", "Value").WithLocation(87, 17), // (90,20): error CS1503: Argument 2: cannot convert from 'ref T' to 'ref T?' // F5(t5, ref s18); // 24 Diagnostic(ErrorCode.ERR_BadArgType, "s18").WithArguments("2", "ref T", "ref T?").WithLocation(90, 20), // (91,17): error CS1061: 'T' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) // _ = s18.Value; // 25 Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Value").WithArguments("T", "Value").WithLocation(91, 17), // (95,9): error CS0411: The type arguments for method 'Program.F1(T, ref T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // F1(t5, ref s19); // 26 Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F1").WithArguments("Program.F1(T, ref T)").WithLocation(95, 9), // (96,17): error CS1061: 'T' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) // _ = s19.Value; // 27 Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Value").WithArguments("T", "Value").WithLocation(96, 17), // (99,20): error CS1503: Argument 2: cannot convert from 'ref T' to 'ref T?' // F5(t5, ref s20); // 28 Diagnostic(ErrorCode.ERR_BadArgType, "s20").WithArguments("2", "ref T", "ref T?").WithLocation(99, 20), // (100,17): error CS1061: 'T' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) // _ = s20.Value; // 29 Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Value").WithArguments("T", "Value").WithLocation(100, 17) ); } [Fact] public void MaybeNull_RefParameter_03() { // Should we enforce nullability annotation attributes inside method bodies? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([MaybeNull]ref string t) { t = null; } // 0 static void F2([MaybeNull]ref string? t) { t = null; } static void M() { string t1 = null!; F1(ref t1); // 1 t1.ToString(); // 2 string? t2 = null; F1(ref t2); // 3 t2.ToString(); // 4 string? t3 = null!; F2(ref t3); t3.ToString(); // 5 } }"; var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (4,51): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F1([MaybeNull]ref string t) { t = null; } // 0 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 51), // (9,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // F1(ref t1); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t1").WithLocation(9, 16), // (10,9): warning CS8602: Dereference of a possibly null reference. // t1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(10, 9), // (13,16): warning CS8601: Possible null reference assignment. // F1(ref t2); // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(13, 16), // (14,9): warning CS8602: Dereference of a possibly null reference. // t2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(14, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // t3.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3").WithLocation(18, 9) ); } [Fact] public void NotNull_ReturnValue_01() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 // Should we enforce nullability annotation attributes inside method bodies? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: NotNull] static T F1(T t) => t; [return: NotNull] static T F2(T t) where T : class => t; [return: NotNull] static T? F3(T t) where T : class => t; [return: NotNull] static T F4(T t) where T : struct => t; [return: NotNull] static T? F5(T? t) where T : struct => t; static void M1(T t1) { F1(t1).ToString(); } static void M2(T t2) where T : class { F1(t2).ToString(); F2(t2).ToString(); F3(t2).ToString(); t2 = null; // 1 F1(t2).ToString(); F2(t2).ToString(); // 2 F3(t2).ToString(); // 3 } static void M3(T? t3) where T : class { F1(t3).ToString(); F2(t3).ToString(); // 4 F3(t3).ToString(); // 5 if (t3 == null) return; F1(t3).ToString(); F2(t3).ToString(); F3(t3).ToString(); } static void M4(T t4) where T : struct { F1(t4).ToString(); F4(t4).ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5).Value; _ = F5(t5).Value; if (t5 == null) return; _ = F1(t5).Value; _ = F5(t5).Value; } }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (20,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(20, 9), // (21,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T)", "T", "T?").WithLocation(21, 9), // (26,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T)", "T", "T?").WithLocation(26, 9), // (27,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t3).ToString(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T)", "T", "T?").WithLocation(27, 9)); } [Fact] public void NotNull_ReturnValue_02() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: NotNull] static T F1(T t) => t; [return: NotNull] static T F2(T t) where T : class => t; [return: NotNull] static T? F3(T t) where T : class => t; [return: NotNull] static T F4(T t) where T : struct => t; [return: NotNull] static T? F5(T? t) where T : struct => t; static void M1(T t1) { F1(t1).ToString(); } static void M2(T t2) where T : class { F1(t2).ToString(); F2(t2).ToString(); F3(t2).ToString(); t2 = null; // 1 F1(t2).ToString(); // 2 F2(t2).ToString(); // 3 F3(t2).ToString(); // 4 } static void M3(T? t3) where T : class { F1(t3).ToString(); // 5 F2(t3).ToString(); // 6 F3(t3).ToString(); // 7 if (t3 == null) return; F1(t3).ToString(); F2(t3).ToString(); F3(t3).ToString(); } static void M4(T t4) where T : struct { F1(t4).ToString(); F4(t4).ToString(); } static void M5(T? t5) where T : struct { _ = F1(t5).Value; _ = F5(t5).Value; if (t5 == null) return; _ = F1(t5).Value; _ = F5(t5).Value; } }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(18, 14), // (19,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F1(T t)'. // F1(t2).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T Program.F1(T t)").WithLocation(19, 15), // (20,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F2(T t)'. // F2(t2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T Program.F2(T t)").WithLocation(20, 15), // (21,15): warning CS8604: Possible null reference argument for parameter 't' in 'T? Program.F3(T t)'. // F3(t2).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t2").WithArguments("t", "T? Program.F3(T t)").WithLocation(21, 15), // (25,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F1(T t)'. // F1(t3).ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T Program.F1(T t)").WithLocation(25, 15), // (26,15): warning CS8604: Possible null reference argument for parameter 't' in 'T Program.F2(T t)'. // F2(t3).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T Program.F2(T t)").WithLocation(26, 15), // (27,15): warning CS8604: Possible null reference argument for parameter 't' in 'T? Program.F3(T t)'. // F3(t3).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t3").WithArguments("t", "T? Program.F3(T t)").WithLocation(27, 15)); } [Fact] public void NotNull_ReturnValue_03() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: NotNull] static string F1() => string.Empty; [return: NotNull] static string? F2() => string.Empty; static void M() { F1().ToString(); F2().ToString(); } }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NotNull_ReturnValue_04() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { [return: NotNull] static int F1() => 1; [return: NotNull] static int? F2() => 2; static void M() { F1().ToString(); _ = F2().Value; } }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NotNull_ReturnValue_05() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static T F1(T t) where T : class => t; [return: NotNull] public static T F2(T t) where T : class => t; }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x).ToString(); // 2, 3 F1(y).ToString(); F2(x).ToString(); // 4 F2(y).ToString(); } }"; comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F1(T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F1(x).ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F1").WithArguments("A.F1(T)", "T", "object?").WithLocation(7, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // F1(x).ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x)").WithLocation(7, 9), // (9,9): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'A.F2(T)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // F2(x).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("A.F2(T)", "T", "object?").WithLocation(9, 9) ); } [Fact] public void NotNull_ReturnValue_05_Unconstrained() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { public static T F1(T t) => t; [return: NotNull] public static T F2(T t) => t; }"; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source0 }); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F1(x).ToString(); // 2 F1(y).ToString(); F2(x).ToString(); F2(y).ToString(); } }"; comp = CreateNullableCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8602: Dereference of a possibly null reference. // F1(x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x)").WithLocation(7, 9) ); } [Fact] public void NotNull_ReturnValue_05_Unconstrained_WithMaybeNull() { var source0 = @"using System.Diagnostics.CodeAnalysis; public class A { [return: NotNull, MaybeNull] public static T F2(T t) => t; }"; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, MaybeNullAttributeDefinition, source0 }); comp.VerifyDiagnostics(); var ref0 = comp.EmitToImageReference(); var source = @"class B : A { static void Main() { object x = null; // 1 object? y = new object(); F2(x).ToString(); // 2 F2(y).ToString(); // 3 } }"; comp = CreateNullableCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 20), // (7,9): warning CS8602: Dereference of a possibly null reference. // F2(x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(x)").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // F2(y).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(y)").WithLocation(8, 9) ); } [Fact] public void NotNull_ReturnValue_05_Unconstrained_WithMaybeNull_InSource() { var source = @"using System.Diagnostics.CodeAnalysis; public class A { [return: NotNull, MaybeNull] public static T F2(T t) => t; } class B : A { static void Main() { object x = null; // 1 object? y = new object(); F2(x).ToString(); // 2 F2(y).ToString(); // 3 } }"; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (10,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 20), // (12,9): warning CS8602: Dereference of a possibly null reference. // F2(x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(x)").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // F2(y).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(y)").WithLocation(13, 9) ); } [Fact] public void NotNull_ReturnValue_06() { var source = @"using System.Diagnostics.CodeAnalysis; class C { [return: NotNull] internal static T F() => throw null!; } class Program { static void M() where U : class where V : struct { C.F().ToString(); C.F().ToString(); C.F().ToString(); C.F().ToString(); _ = C.F().Value; C.F().ToString(); C.F().ToString(); C.F().ToString(); _ = C.F().Value; } }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NotNull_Property() { // Warn on misused nullability attributes (P3, P5)? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [NotNull]public TOpen P1 { get; set; } = default!; } public class CClass where TClass : class { [NotNull]public TClass P2 { get; set; } = null!; [NotNull]public TClass? P3 { get; set; } = null; } public class CStruct where TStruct : struct { [NotNull]public TStruct P4 { get; set; } [NotNull]public TStruct? P5 { get; set; } }"; var lib = CreateNullableCompilation(new[] { lib_cs, NotNullAttributeDefinition }); var source = @" class C { static void M1(T t1) { new COpen().P1.ToString(); } static void M2(T t2) where T : class { new COpen().P1.ToString(); new CClass().P2.ToString(); new CClass().P3.ToString(); } static void M4(T t4) where T : struct { new COpen().P1.ToString(); new CStruct().P4.ToString(); } static void M5(T? t5) where T : struct { new COpen().P1.Value.ToString(); new CStruct().P5.Value.ToString(); } }"; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, NotNullAttributeDefinition }); comp2.VerifyDiagnostics(); } [Fact] public void NotNull_Property_OnVirtualProperty() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [NotNull] public virtual string? P => throw null!; public virtual string? P2 => throw null!; } public class C : Base { public override string? P => throw null!; [NotNull] public override string? P2 => throw null!; static void M(C c, Base b) { b.P.ToString(); c.P.ToString(); // 1 b.P2.ToString(); // 2 c.P2.ToString(); } }"; var comp = CreateNullableCompilation(new[] { source, NotNullAttributeDefinition }); comp.VerifyDiagnostics( // (16,9): warning CS8602: Dereference of a possibly null reference. // c.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(16, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // b.P2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.P2").WithLocation(18, 9) ); } [Fact] public void NotNull_Property_OnVirtualProperty_OnlyOverridingGetter() { // Consider warning on improper nullability attributes in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @" using System.Diagnostics.CodeAnalysis; public class Base { [NotNull] public virtual string? P { get { throw null!; } set { throw null!; } } public virtual string? P2 { get { throw null!; } set { throw null!; } } } public class C : Base { public override string? P { get { throw null!; } } [NotNull] public override string? P2 { get { throw null!; } } static void M(C c, Base b) { b.P.ToString(); c.P.ToString(); // 1 b.P2.ToString(); // 2 c.P2.ToString(); } }"; var comp = CreateNullableCompilation(new[] { source, NotNullAttributeDefinition }); comp.VerifyDiagnostics( // (16,9): warning CS8602: Dereference of a possibly null reference. // c.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(16, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // b.P2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.P2").WithLocation(18, 9) ); } [Fact] public void NotNull_01_Indexer() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 var lib_cs = @"using System.Diagnostics.CodeAnalysis; public class COpen { [NotNull]public TOpen this[int i] { get => throw null!; } } public class CClass where TClass : class? { [NotNull]public TClass this[int i] { get => throw null!; } } public class CClass2 where TClass : class { [NotNull]public TClass? this[int i] { get => throw null!; } } public class CStruct where TStruct : struct { [NotNull]public TStruct this[int i] { get => throw null!; } } public class CStruct2 where TStruct : struct { [NotNull]public TStruct? this[int i] { get => throw null!; } }"; var lib = CreateNullableCompilation(new[] { lib_cs, NotNullAttributeDefinition }); lib.VerifyDiagnostics(); var source = @" class C { static void M1(T t1) { new COpen()[0].ToString(); } static void M2(T t2) where T : class { new COpen()[0].ToString(); new CClass()[0].ToString(); new CClass2()[0].ToString(); } static void M4(T t4) where T : struct { new COpen()[0].ToString(); new CStruct()[0].ToString(); new COpen()[0].Value.ToString(); new CStruct2()[0].Value.ToString(); } }"; var comp = CreateNullableCompilation(source, references: new[] { lib.EmitToImageReference() }); comp.VerifyDiagnostics(); var comp2 = CreateNullableCompilation(new[] { source, lib_cs, NotNullAttributeDefinition }); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var copen = (NamedTypeSymbol)m.GlobalNamespace.GetMember("COpen"); var copenAttributes = copen.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Empty(copenAttributes); } else { AssertEx.Equal(new[] { "System.Runtime.CompilerServices.NullableContextAttribute(1)", "System.Runtime.CompilerServices.NullableAttribute(0)", "System.Reflection.DefaultMemberAttribute(\"Item\")" }, copenAttributes); } var property = copen.GetMembers().OfType().Single(); var propertyAttributes = property.GetAttributes().Select(a => a.ToString()); if (isSource) { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.NotNullAttribute" }, propertyAttributes); } else { AssertEx.Empty(propertyAttributes); } var getter = property.GetMethod; Assert.Empty(getter.GetAttributes()); var getterReturnAttributes = getter.GetReturnTypeAttributes().Select(a => a.ToString()); Assert.Equal(FlowAnalysisAnnotations.NotNull, getter.ReturnTypeFlowAnalysisAnnotations); if (isSource) { AssertEx.Empty(getterReturnAttributes); } else { AssertEx.Equal(new[] { "System.Diagnostics.CodeAnalysis.NotNullAttribute" }, getterReturnAttributes); } } } [Fact] public void NotNull_01_Indexer_Implementation() { // Should we enforce nullability annotation attributes inside method bodies? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class CClass2 where TClass : class { [NotNull]public TClass? this[int i] { get => null; } // consider warning }"; var comp = CreateNullableCompilation(new[] { source, NotNullAttributeDefinition }); comp.VerifyDiagnostics(); } [Fact, WorkItem(35949, "https://github.com/dotnet/roslyn/issues/35949")] public void NotNull_Complexity() { var source = @" using System; using System.Diagnostics.CodeAnalysis; class C { C f = null!; void M(C c) { c.f = c; c.NotNull( x => x.f.NotNull( y => y.f.NotNull( z => z.f.NotNull( q => q.f.NotNull( w => w.f.NotNull( e => e.f.NotNull( r => r.f.NotNull( _ => { """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); """".NotNull(s => s); return """"; })))))))); } } static class Ext { public static V NotNull([NotNull] this T t, Func f) => throw null!; } "; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void NotNull_OutParameter_GenericType() { // Warn on misused nullability attributes? https://github.com/dotnet/roslyn/issues/36073 // Should we enforce nullability annotation attributes inside method bodies? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1(T t, [NotNull]out T t2) { t2 = t; } static void F2(T t, [NotNull]out T t2) where T : class { t2 = t; } static void F3(T t, [NotNull]out T? t2) where T : class { t2 = t; } static void F4(T t, [NotNull]out T t2) where T : struct { t2 = t; } static void F5(T? t, [NotNull]out T? t2) where T : struct { t2 = t; } static void M1(T t1) { F1(t1, out var s1); s1.ToString(); } static void M2(T t2) where T : class { F1(t2, out var s2); s2.ToString(); F2(t2, out var s3); s3.ToString(); F3(t2, out var s4); s4.ToString(); t2 = null; // 1 F1(t2, out var s5); s5.ToString(); F2(t2, out var s6); // 2 s6.ToString(); F3(t2, out var s7); // 3 s7.ToString(); } static void M3(T? t3) where T : class { F1(t3, out var s8); s8.ToString(); F2(t3, out var s9); // 4 s9.ToString(); F3(t3, out var s10); // 5 s10.ToString(); if (t3 == null) return; F1(t3, out var s11); s11.ToString(); F2(t3, out var s12); s12.ToString(); F3(t3, out var s13); s13.ToString(); } static void M4(T t4) where T : struct { F1(t4, out var s14); s14.ToString(); F4(t4, out var s15); s15.ToString(); } static void M5(T? t5) where T : struct { F1(t5, out var s16); _ = s16.Value; F5(t5, out var s17); _ = s17.Value; if (t5 == null) return; F1(t5, out var s18); _ = s18.Value; F5(t5, out var s19); _ = s19.Value; } }"; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t2 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(25, 14), // (29,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t2, out var s6); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(29, 9), // (32,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t2, out var s7); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(32, 9), // (40,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F2(T, out T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F2(t3, out var s9); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F2").WithArguments("Program.F2(T, out T)", "T", "T?").WithLocation(40, 9), // (43,9): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.F3(T, out T?)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // F3(t3, out var s10); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F3").WithArguments("Program.F3(T, out T?)", "T", "T?").WithLocation(43, 9)); } [Fact] public void NotNull_RefParameter_03() { // Should we enforce nullability annotation attributes inside method bodies? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F1([NotNull]ref string t) { t = null; } // 0 static void F2([NotNull]ref string? t) { t = null; } static void M() { string t1 = null; // 1 F1(ref t1); // 2 t1.ToString(); string? t2 = null; F1(ref t2); // 3 t2.ToString(); string? t3 = null; F2(ref t3); t3.ToString(); } }"; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (4,49): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F1([NotNull]ref string t) { t = null; } // 0 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 49), // (8,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string t1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 21), // (9,16): warning CS8601: Possible null reference assignment. // F1(ref t1); // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t1").WithLocation(9, 16), // (13,16): warning CS8601: Possible null reference assignment. // F1(ref t2); // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t2").WithLocation(13, 16) ); } [Fact] public void NotNull_OHI_ReturnValue_GenericType_Loosening() { // Should we require nullability annotation attributes to match or vary properly in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class Base { [return: NotNull] public virtual T F1(T t) => t; [return: NotNull] public virtual T F2(T t) where T : class => t; [return: NotNull] public virtual T? F3(T t) where T : class => t; [return: NotNull] public virtual T F4(T t) where T : struct => t; [return: NotNull] public virtual T? F5(T t) where T : struct => t; } public class Derived : Base { public override T F1(T t) => t; public override T F2(T t) where T : class => t; public override T? F3(T t) where T : class => t; public override T F4(T t) where T : struct => t; public override T? F5(T t) where T : struct => t; } "; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void NotNull_OHI_ReturnValue_GenericType_Loosening_MaybeNull() { // Should we require nullability annotation attributes to match or vary properly in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class Base { [return: NotNull] public virtual T F1() => throw null!; [return: NotNull] public virtual T F2() where T : class => throw null!; [return: NotNull] public virtual T? F3() where T : class => throw null!; [return: NotNull] public virtual T F4() where T : struct => throw null!; [return: NotNull] public virtual T? F5() where T : struct => throw null!; } public class Derived : Base { [return: MaybeNull] public override T F1() => throw null!; [return: MaybeNull] public override T F2() where T : class => throw null!; [return: MaybeNull] public override T? F3() where T : class => throw null!; [return: MaybeNull] public override T F4() where T : struct => throw null!; [return: MaybeNull] public override T? F5() where T : struct => throw null!; } "; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void NotNull_OHI_OutParameter_GenericType_Loosening() { // Should we require nullability annotation attributes to match or vary properly in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class Base { public virtual void F1([NotNull]out T t2) => throw null!; public virtual void F2([NotNull]out T t2) where T : class => throw null!; public virtual void F3([NotNull]out T? t2) where T : class => throw null!; public virtual void F4([NotNull]out T t2) where T : struct => throw null!; public virtual void F5([NotNull]out T? t2) where T : struct => throw null!; } public class Derived : Base { public override void F1(out T t2) => throw null!; public override void F2(out T t2) where T : class => throw null!; public override void F3(out T? t2) where T : class => throw null!; public override void F4(out T t2) where T : struct => throw null!; public override void F5(out T? t2) where T : struct => throw null!; } "; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void NotNull_OHI_ReturnValue_GenericType_Tightening() { // Should we require nullability annotation attributes to match or vary properly in OHI? https://github.com/dotnet/roslyn/issues/36039 var source = @"using System.Diagnostics.CodeAnalysis; public class Derived : Base { [return: NotNull] public override T F1(T t) => t; [return: NotNull] public override T F2(T t) where T : class => t; [return: NotNull] public override T? F3(T t) where T : class => t; [return: NotNull] public override T F4(T t) where T : struct => t; [return: NotNull] public override T? F5(T t) where T : struct => t; } public class Base { public virtual T F1(T t) => t; public virtual T F2(T t) where T : class => t; public virtual T? F3(T t) where T : class => t; public virtual T F4(T t) where T : struct => t; public virtual T? F5(T t) where T : struct => t; } "; var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics(); } [Fact] public void NullableAnnotationAttributes_Deconstruction() { var source = @"using System.Diagnostics.CodeAnalysis; class Pair { internal void Deconstruct([MaybeNull] out T t, [NotNull] out U u) => throw null!; } class Program { static void F1(Pair p) { var (x1, y1) = p; x1.ToString(); // 1 y1.ToString(); } static void F2(Pair p) where T : class { var (x2, y2) = p; x2.ToString(); // 2 y2.ToString(); } static void F3(Pair p) where T : class? { var (x3, y3) = p; x3.ToString(); // 3 y3.ToString(); } static void F4(Pair p) where T : struct { var (x4, y4) = p; _ = x4.Value; // 4 _ = y4.Value; } }"; var comp = CreateCompilation(new[] { MaybeNullAttributeDefinition, NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(11, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(17, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // x3.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(23, 9), // (29,13): warning CS8629: Nullable value type may be null. // _ = x4.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x4").WithLocation(29, 13)); } [Fact] public void NullableAnnotationAttributes_ExtensionMethodThis() { var source = @"using System.Diagnostics.CodeAnalysis; delegate void D(); static class Program { static void E1([AllowNull] this T t) where T : class { } static void E2([DisallowNull] this T t) where T : class? { } static void F1(T t1) where T : class { D d; d = t1.E1; d = t1.E2; t1 = null; // 1 d = t1.E1; // 2 d = t1.E2; // 3 } static void F2(T t2) where T : class? { D d; d = t2.E1; // 4 d = t2.E2; // 5 } }"; var comp = CreateCompilation(new[] { AllowNullAttributeDefinition, DisallowNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 14), // (13,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'Program.E1(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // d = t1.E1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "t1.E1").WithArguments("Program.E1(T)", "T", "T?").WithLocation(13, 13), // (14,13): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.E2(T? t)'. // d = t1.E2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t1").WithArguments("t", "void Program.E2(T? t)").WithLocation(14, 13), // (19,13): warning CS8634: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Program.E1(T)'. Nullability of type argument 'T' doesn't match 'class' constraint. // d = t2.E1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "t2.E1").WithArguments("Program.E1(T)", "T", "T").WithLocation(19, 13)); } [Fact] public void ConditionalBranching_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 x1, CL1? y1, CL1 z1) { if (y1 != null) { x1 = y1; } else { z1 = y1; } } void Test2(CL1 x2, CL1? y2, CL1 z2) { if (y2 == null) { x2 = y2; } else { z2 = y2; } } void Test3(CL2 x3, CL2? y3, CL2 z3) { if (y3 != null) { x3 = y3; } else { z3 = y3; } } void Test4(CL2 x4, CL2? y4, CL2 z4) { if (y4 == null) { x4 = y4; } else { z4 = y4; } } void Test5(CL1 x5, CL1 y5, CL1 z5) { if (y5 != null) { x5 = y5; } else { z5 = y5; } } } class CL1 { } class CL2 { public static bool operator == (CL2? x, CL2? y) { return false; } public static bool operator != (CL2? x, CL2? y) { return false; } public override bool Equals(object obj) { return false; } public override int GetHashCode() { return 0; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z1 = y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(16, 18), // (24,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2").WithLocation(24, 18), // (40,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z3 = y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y3").WithLocation(40, 18), // (48,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(48, 18), // (64,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z5 = y5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y5").WithLocation(64, 18) ); } [Fact] public void ConditionalBranching_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 x1, CL1? y1, CL1 z1) { if (null != y1) { x1 = y1; } else { z1 = y1; } } void Test2(CL1 x2, CL1? y2, CL1 z2) { if (null == y2) { x2 = y2; } else { z2 = y2; } } void Test3(CL2 x3, CL2? y3, CL2 z3) { if (null != y3) { x3 = y3; } else { z3 = y3; } } void Test4(CL2 x4, CL2? y4, CL2 z4) { if (null == y4) { x4 = y4; } else { z4 = y4; } } void Test5(CL1 x5, CL1 y5, CL1 z5) { if (null == y5) { x5 = y5; } else { z5 = y5; } } } class CL1 { } class CL2 { public static bool operator == (CL2? x, CL2? y) { return false; } public static bool operator != (CL2? x, CL2? y) { return false; } public override bool Equals(object obj) { return false; } public override int GetHashCode() { return 0; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z1 = y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(16, 18), // (24,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2").WithLocation(24, 18), // (40,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z3 = y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y3").WithLocation(40, 18), // (48,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4").WithLocation(48, 18), // (60,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = y5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y5").WithLocation(60, 18) ); } [Fact] public void ConditionalBranching_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 x1, CL1? y1, CL1 z1, bool u1) { if (null != y1 || u1) { x1 = y1; } else { z1 = y1; } } void Test2(CL1 x2, CL1? y2, CL1 z2, bool u2) { if (y2 != null && u2) { x2 = y2; } else { z2 = y2; } } bool Test3(CL1? x3) { return x3.M1(); } bool Test4(CL1? x4) { return x4 != null && x4.M1(); } bool Test5(CL1? x5) { return x5 == null && x5.M1(); } } class CL1 { public bool M1() { return true; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(12, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z1 = y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(16, 18), // (28,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z2 = y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2").WithLocation(28, 18), // (34,16): warning CS8602: Dereference of a possibly null reference. // return x3.M1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(34, 16), // (44,30): warning CS8602: Dereference of a possibly null reference. // return x5 == null && x5.M1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x5").WithLocation(44, 30) ); } [Fact] public void ConditionalBranching_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 x1, CL1? y1) { CL1 z1 = y1 ?? x1; } void Test2(CL1? x2, CL1? y2) { CL1 z2 = y2 ?? x2; } void Test3(CL1 x3, CL1? y3) { CL1 z3 = x3 ?? y3; } void Test4(CL1? x4, CL1 y4) { x4 = y4; CL1 z4 = x4 ?? x4.M1(); } void Test5(CL1 x5) { const CL1? y5 = null; CL1 z5 = y5 ?? x5; } void Test6(CL1 x6) { const string? y6 = """"; string z6 = y6 ?? x6.M2(); } } class CL1 { public CL1 M1() { return new CL1(); } public string? M2() { return null; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = y2 ?? x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 ?? x2").WithLocation(15, 18), // (20,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z3 = x3 ?? y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 ?? y3").WithLocation(20, 18), // (26,24): warning CS8602: Dereference of a possibly null reference. // CL1 z4 = x4 ?? x4.M1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4").WithLocation(26, 24)); } [Fact] public void ConditionalBranching_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1? x1) { CL1 z1 = x1?.M1(); } void Test2(CL1? x2, CL1 y2) { x2 = y2; CL1 z2 = x2?.M1(); } void Test3(CL1? x3, CL1 y3) { x3 = y3; CL1 z3 = x3?.M2(); } void Test4(CL1? x4) { x4?.M3(x4); } } class CL1 { public CL1 M1() { return new CL1(); } public CL1? M2() { return null; } public void M3(CL1 x) { } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z1 = x1?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1?.M1()").WithLocation(10, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = x2?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2?.M1()").WithLocation(16, 18), // (22,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z3 = x3?.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3?.M2()").WithLocation(22, 18) ); } [Fact] public void ConditionalBranching_06() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 x1, CL1? y1) { CL1 z1 = y1 != null ? y1 : x1; } void Test2(CL1? x2, CL1? y2) { CL1 z2 = y2 != null ? y2 : x2; } void Test3(CL1 x3, CL1? y3) { CL1 z3 = x3 != null ? x3 : y3; } void Test4(CL1? x4, CL1 y4) { x4 = y4; CL1 z4 = x4 != null ? x4 : x4.M1(); } void Test5(CL1 x5) { const CL1? y5 = null; CL1 z5 = y5 != null ? y5 : x5; } void Test6(CL1 x6) { const string? y6 = """"; string z6 = y6 != null ? y6 : x6.M2(); } void Test7(CL1 x7) { const string? y7 = null; string z7 = y7 != null ? y7 : x7.M2(); } } class CL1 { public CL1 M1() { return new CL1(); } public string? M2() { return null; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = y2 != null ? y2 : x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 != null ? y2 : x2").WithLocation(15, 18), // (20,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z3 = x3 != null ? x3 : y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 != null ? x3 : y3").WithLocation(20, 18), // (26,36): warning CS8602: Dereference of a possibly null reference. // CL1 z4 = x4 != null ? x4 : x4.M1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4").WithLocation(26, 36), // (44,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string z7 = y7 != null ? y7 : x7.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y7 != null ? y7 : x7.M2()").WithLocation(44, 21) ); } [Fact] public void ConditionalBranching_07() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 x1, CL1? y1) { CL1 z1 = y1 == null ? x1 : y1; } void Test2(CL1? x2, CL1? y2) { CL1 z2 = y2 == null ? x2 : y2; } void Test3(CL1 x3, CL1? y3) { CL1 z3 = x3 == null ? y3 : x3; } void Test4(CL1? x4, CL1 y4) { x4 = y4; CL1 z4 = x4 == null ? x4.M1() : x4; } void Test5(CL1 x5) { const CL1? y5 = null; CL1 z5 = y5 == null ? x5 : y5; } void Test6(CL1 x6) { const string? y6 = """"; string z6 = y6 == null ? x6.M2() : y6; } void Test7(CL1 x7) { const string? y7 = null; string z7 = y7 == null ? x7.M2() : y7; } } class CL1 { public CL1 M1() { return new CL1(); } public string? M2() { return null; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = y2 == null ? x2 : y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 == null ? x2 : y2").WithLocation(15, 18), // (20,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z3 = x3 == null ? y3 : x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 == null ? y3 : x3").WithLocation(20, 18), // (26,31): warning CS8602: Dereference of a possibly null reference. // CL1 z4 = x4 == null ? x4.M1() : x4; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4").WithLocation(26, 31), // (44,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // string z7 = y7 == null ? x7.M2() : y7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y7 == null ? x7.M2() : y7").WithLocation(44, 21) ); } [Fact] [WorkItem(26624, "https://github.com/dotnet/roslyn/issues/26624")] public void ConditionalBranching_08() { CSharpCompilation c = CreateCompilation(@" class C { bool Test1(CL1? x1) { if (x1?.P1 == true) { return x1.P2; } return x1.P2; // 1 } } class CL1 { public bool P1 { get { return true;} } public bool P2 { get { return true;} } } ", options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,16): warning CS8602: Dereference of a possibly null reference. // return x1.P2; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(11, 16) ); } [Fact] public void ConditionalBranching_09() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(object x1, object? y1) { y1 = x1; y1.ToString(); object z1 = y1 ?? x1; y1.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(13, 9)); } [Fact] public void ConditionalBranching_10() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(object x1, object? y1) { y1 = x1; y1.ToString(); object z1 = y1 != null ? y1 : x1; y1.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(13, 9) ); } [Fact] public void ConditionalBranching_11() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Test1(object x1, object? y1) { y1 = x1; y1.ToString(); y1?.GetHashCode(); y1.ToString(); // 1 } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(9, 9) ); } [Fact] public void ConditionalBranching_12() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(object x1, object? y1) { y1 = x1; y1.ToString(); if (y1 == null) { System.Console.WriteLine(1); } else { System.Console.WriteLine(2); } y1.ToString(); // 1 } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (22,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(22, 9) ); } [Fact] public void ConditionalBranching_13() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(object x1, object? y1) { y1 = x1; y1.ToString(); if (y1 != null) { System.Console.WriteLine(1); } else { System.Console.WriteLine(2); } y1.ToString(); // 1 } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (22,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(22, 9) ); } [Fact] public void ConditionalBranching_14() { var compilation = CreateCompilation(new[] { @" class C { C? _cField = null; C _nonNullCField = new C(); C? GetC() => null; C? CProperty { get => null; } void Test1(C? c1) { if (c1?._cField != null) { c1._cField.ToString(); } else { c1._cField.ToString(); // warn 1 2 } } void Test2() { C? c2 = GetC(); if (c2?._cField != null) { c2._cField.ToString(); } else { c2._cField.ToString(); // warn 3 4 } } void Test3(C? c3) { if (c3?._cField?._cField != null) { c3._cField._cField.ToString(); } else if (c3?._cField != null) { c3._cField.ToString(); c3._cField._cField.ToString(); // warn 5 } else { c3.ToString(); // warn 6 } } void Test4(C? c4) { if (c4?._nonNullCField._cField?._nonNullCField._cField != null) { c4._nonNullCField._cField._nonNullCField._cField.ToString(); } else { c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9 } } void Test5(C? c5) { if (c5?._cField == null) { c5._cField.ToString(); // warn 10 11 } else { c5._cField.ToString(); } } void Test6(C? c6) { if (c6?._cField?.GetC() != null) { c6._cField.GetC().ToString(); // warn 12 } } void Test7(C? c7) { if (c7?._cField?.CProperty != null) { c7._cField.CProperty.ToString(); } } } " }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (17,13): warning CS8602: Dereference of a possibly null reference. // c1._cField.ToString(); // warn 1 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(17, 13), // (17,13): warning CS8602: Dereference of a possibly null reference. // c1._cField.ToString(); // warn 1 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1._cField").WithLocation(17, 13), // (30,13): warning CS8602: Dereference of a possibly null reference. // c2._cField.ToString(); // warn 3 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(30, 13), // (30,13): warning CS8602: Dereference of a possibly null reference. // c2._cField.ToString(); // warn 3 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2._cField").WithLocation(30, 13), // (43,13): warning CS8602: Dereference of a possibly null reference. // c3._cField._cField.ToString(); // warn 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3._cField._cField").WithLocation(43, 13), // (47,13): warning CS8602: Dereference of a possibly null reference. // c3.ToString(); // warn 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(47, 13), // (59,13): warning CS8602: Dereference of a possibly null reference. // c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4").WithLocation(59, 13), // (59,13): warning CS8602: Dereference of a possibly null reference. // c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4._nonNullCField._cField").WithLocation(59, 13), // (59,13): warning CS8602: Dereference of a possibly null reference. // c4._nonNullCField._cField._nonNullCField._cField.ToString(); // warn 7 8 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4._nonNullCField._cField._nonNullCField._cField").WithLocation(59, 13), // (67,13): warning CS8602: Dereference of a possibly null reference. // c5._cField.ToString(); // warn 10 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c5").WithLocation(67, 13), // (67,13): warning CS8602: Dereference of a possibly null reference. // c5._cField.ToString(); // warn 10 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c5._cField").WithLocation(67, 13), // (79,13): warning CS8602: Dereference of a possibly null reference. // c6._cField.GetC().ToString(); // warn 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c6._cField.GetC()").WithLocation(79, 13) ); } [Fact] public void ConditionalBranching_15() { var compilation = CreateCompilation(new[] { @" class C { void Test(C? c1) { if (c1?[0] != null) { c1.ToString(); c1[0].ToString(); // warn 1 } else { c1.ToString(); // warn 2 } } object? this[int i] { get => null; } } " }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // c1[0].ToString(); // warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1[0]").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // c1.ToString(); // warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(13, 13) ); } [Fact] public void ConditionalBranching_16() { var compilation = CreateCompilation(new[] { @" class C { void Test(T t) { if (t?.ToString() != null) { t.ToString(); } else { t.ToString(); // warn } } }" }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(12, 13) ); } [Fact] public void ConditionalBranching_17() { var compilation = CreateCompilation(new[] { @" class C { object? Prop { get; } object? GetObj(bool val) => null; void Test(C? c1, C? c2) { if (c1?.GetObj(c2?.Prop != null) != null) { c2.Prop.ToString(); // warn 1 2 } } }" }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // c2.Prop.ToString(); // warn 1 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(10, 13), // (10,13): warning CS8602: Dereference of a possibly null reference. // c2.Prop.ToString(); // warn 1 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2.Prop").WithLocation(10, 13) ); } [Fact] public void ConditionalBranching_18() { var compilation = CreateCompilation(new[] { @" class C { void Test(C? x, C? y) { if ((x = y)?.GetHashCode() != null) { x.ToString(); y.ToString(); // warn } } }" }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 13) ); } [Fact] public void ConditionalBranching_Is_ReferenceType() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void Test(object? x) { if (x is C) { x.ToString(); } else { x.ToString(); // warn } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(12, 13) ); } [Fact] public void ConditionalBranching_Is_GenericType() { CSharpCompilation c = CreateCompilation(new[] { @" class Base { } class C : Base { void Test(C? x) where T : Base { if (x is T) { x.ToString(); } else { x.ToString(); // warn } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13) ); } [Fact] public void ConditionalBranching_Is_UnconstrainedGenericType() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void F(object? o) { if (o is T) { o.ToString(); } else { o.ToString(); // warn } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(12, 13) ); } [Fact] public void ConditionalBranching_Is_StructConstrainedGenericType() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void F(object? o) where T : struct { if (o is T) { o.ToString(); } else { o.ToString(); // warn } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(12, 13) ); } [Fact] public void ConditionalBranching_Is_ClassConstrainedGenericType() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void F(object? o) where T : class { if (o is T) { o.ToString(); } else { o.ToString(); // warn } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,13): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(12, 13) ); } [Fact] public void ConditionalBranching_Is_UnconstrainedGenericOperand() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void F(T t, object? o) { if (t is string) t.ToString(); if (t is string s) { t.ToString(); s.ToString(); } if (t != null) t.ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void ConditionalBranching_Is_NullOperand() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void F(object? o) { if (null is string) return; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (6,13): warning CS0184: The given expression is never of the provided ('string') type // if (null is string) return; Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "null is string").WithArguments("string").WithLocation(6, 13) ); } [Fact] public void ConditionalOperator_01() { var source = @"class C { static void F(bool b, object x, object? y) { var z = b ? x : y; z.ToString(); var w = b ? y : x; w.ToString(); var v = true ? y : x; v.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // w.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // v.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v").WithLocation(10, 9)); } [Fact] public void ConditionalOperator_02() { var source = @"class C { static void F(bool b, object x, object? y) { (b ? x : y).ToString(); (b ? y : x).ToString(); if (y != null) (b ? x : y).ToString(); if (y != null) (b ? y : x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,10): warning CS8602: Dereference of a possibly null reference. // (b ? x : y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : y").WithLocation(5, 10), // (6,10): warning CS8602: Dereference of a possibly null reference. // (b ? y : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y : x").WithLocation(6, 10)); } [Fact] public void ConditionalOperator_03() { var source = @"class C { static void F(object x, object? y) { (false ? x : y).ToString(); (false ? y : x).ToString(); (true ? x : y).ToString(); (true ? y : x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,10): warning CS8602: Dereference of a possibly null reference. // (false ? x : y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "false ? x : y").WithLocation(5, 10), // (8,10): warning CS8602: Dereference of a possibly null reference. // (true ? y : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "true ? y : x").WithLocation(8, 10)); } [Fact] public void ConditionalOperator_04() { var source = @"class C { static void F(bool b, object x, string? y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } static void G(bool b, object? x, string y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,10): warning CS8602: Dereference of a possibly null reference. // (b ? x : y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : y").WithLocation(5, 10), // (6,10): warning CS8602: Dereference of a possibly null reference. // (b ? y : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y : x").WithLocation(6, 10), // (10,10): warning CS8602: Dereference of a possibly null reference. // (b ? x : y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : y").WithLocation(10, 10), // (11,10): warning CS8602: Dereference of a possibly null reference. // (b ? y : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y : x").WithLocation(11, 10)); } [Fact] public void ConditionalOperator_05() { var source = @"#pragma warning disable 0649 class A { } class B1 : A { } class B2 : A { } class C { static void F(bool b, A x, A y, B1 z, B2 w) { object o; o = (b ? x : z)/*T:A!*/; o = (b ? x : w)/*T:A!*/; o = (b ? z : x)/*T:A!*/; o = (b ? w : x)/*T:A!*/; o = (b ? y : z)/*T:A!*/; o = (b ? y : w)/*T:A!*/; o = (b ? z : y)/*T:A!*/; o = (b ? w : y)/*T:A!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,22): warning CS8619: Nullability of reference types in value of type 'B1' doesn't match target type 'A'. // o = (b ? x : z)/*T:A!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z").WithArguments("B1", "A").WithLocation(10, 22), // (12,18): warning CS8619: Nullability of reference types in value of type 'B1' doesn't match target type 'A'. // o = (b ? z : x)/*T:A!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z").WithArguments("B1", "A").WithLocation(12, 18), // (15,22): warning CS8619: Nullability of reference types in value of type 'B2' doesn't match target type 'A'. // o = (b ? y : w)/*T:A!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("B2", "A").WithLocation(15, 22), // (17,18): warning CS8619: Nullability of reference types in value of type 'B2' doesn't match target type 'A'. // o = (b ? w : y)/*T:A!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("B2", "A").WithLocation(17, 18)); } [Fact] public void ConditionalOperator_06() { var source = @"class C { static void F(bool b, object x, string? y) { (b ? null : x).ToString(); (b ? null : y).ToString(); (b ? x: null).ToString(); (b ? y: null).ToString(); (b ? null: null).ToString(); (b ? default : x).ToString(); (b ? default : y).ToString(); (b ? x: default).ToString(); (b ? y: default).ToString(); (b ? default: default).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between '' and '' // (b ? null: null).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? null: null").WithArguments("", "").WithLocation(9, 10), // (14,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'default' and 'default' // (b ? default: default).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? default: default").WithArguments("default", "default").WithLocation(14, 10), // (5,10): warning CS8602: Dereference of a possibly null reference. // (b ? null : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? null : x").WithLocation(5, 10), // (6,10): warning CS8602: Dereference of a possibly null reference. // (b ? null : y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? null : y").WithLocation(6, 10), // (7,10): warning CS8602: Dereference of a possibly null reference. // (b ? x: null).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x: null").WithLocation(7, 10), // (8,10): warning CS8602: Dereference of a possibly null reference. // (b ? y: null).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y: null").WithLocation(8, 10), // (10,10): warning CS8602: Dereference of a possibly null reference. // (b ? default : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? default : x").WithLocation(10, 10), // (11,10): warning CS8602: Dereference of a possibly null reference. // (b ? default : y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? default : y").WithLocation(11, 10), // (12,10): warning CS8602: Dereference of a possibly null reference. // (b ? x: default).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x: default").WithLocation(12, 10), // (13,10): warning CS8602: Dereference of a possibly null reference. // (b ? y: default).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? y: default").WithLocation(13, 10) ); } [Fact] public void ConditionalOperator_07() { var source = @"class C { static void F(bool b, Unknown x, Unknown? y) { (b ? null : x).ToString(); (b ? null : y).ToString(); (b ? x: null).ToString(); (b ? y: null).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,27): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F(bool b, Unknown x, Unknown? y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 27), // (3,38): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F(bool b, Unknown x, Unknown? y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 38) ); } [Fact] public void ConditionalOperator_08() { var source = @"class C { static void F1(bool b, UnknownA x, UnknownB y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } static void F2(bool b, UnknownA? x, UnknownB y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } static void F3(bool b, UnknownA? x, UnknownB? y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,28): error CS0246: The type or namespace name 'UnknownA' could not be found (are you missing a using directive or an assembly reference?) // static void F2(bool b, UnknownA? x, UnknownB y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownA").WithArguments("UnknownA").WithLocation(8, 28), // (8,41): error CS0246: The type or namespace name 'UnknownB' could not be found (are you missing a using directive or an assembly reference?) // static void F2(bool b, UnknownA? x, UnknownB y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownB").WithArguments("UnknownB").WithLocation(8, 41), // (13,28): error CS0246: The type or namespace name 'UnknownA' could not be found (are you missing a using directive or an assembly reference?) // static void F3(bool b, UnknownA? x, UnknownB? y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownA").WithArguments("UnknownA").WithLocation(13, 28), // (13,41): error CS0246: The type or namespace name 'UnknownB' could not be found (are you missing a using directive or an assembly reference?) // static void F3(bool b, UnknownA? x, UnknownB? y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownB").WithArguments("UnknownB").WithLocation(13, 41), // (3,28): error CS0246: The type or namespace name 'UnknownA' could not be found (are you missing a using directive or an assembly reference?) // static void F1(bool b, UnknownA x, UnknownB y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownA").WithArguments("UnknownA").WithLocation(3, 28), // (3,40): error CS0246: The type or namespace name 'UnknownB' could not be found (are you missing a using directive or an assembly reference?) // static void F1(bool b, UnknownA x, UnknownB y) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UnknownB").WithArguments("UnknownB").WithLocation(3, 40), // (15,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'UnknownA?' and 'UnknownB?' // (b ? x : y).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? x : y").WithArguments("UnknownA?", "UnknownB?").WithLocation(15, 10), // (16,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'UnknownB?' and 'UnknownA?' // (b ? y : x).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("UnknownB?", "UnknownA?").WithLocation(16, 10) ); } [Fact] public void ConditionalOperator_09() { var source = @"struct A { } struct B { } class C { static void F1(bool b, A x, B y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } static void F2(bool b, A x, C y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } static void F3(bool b, B x, C? y) { (b ? x : y).ToString(); (b ? y : x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'A' and 'B' // (b ? x : y).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? x : y").WithArguments("A", "B").WithLocation(7, 10), // (8,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'B' and 'A' // (b ? y : x).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("B", "A").WithLocation(8, 10), // (12,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'A' and 'C' // (b ? x : y).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? x : y").WithArguments("A", "C").WithLocation(12, 10), // (13,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'C' and 'A' // (b ? y : x).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("C", "A").WithLocation(13, 10), // (17,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'B' and 'C' // (b ? x : y).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? x : y").WithArguments("B", "C").WithLocation(17, 10), // (18,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'C' and 'B' // (b ? y : x).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? y : x").WithArguments("C", "B").WithLocation(18, 10) ); } [Fact] public void ConditionalOperator_10() { var source = @"using System; class C { static void F(bool b, object? x, object y) { (b ? x : throw new Exception()).ToString(); (b ? y : throw new Exception()).ToString(); (b ? throw new Exception() : x).ToString(); (b ? throw new Exception() : y).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (b ? x : throw new Exception()).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x : throw new Exception()").WithLocation(6, 10), // (8,10): warning CS8602: Dereference of a possibly null reference. // (b ? throw new Exception() : x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? throw new Exception() : x").WithLocation(8, 10)); } [Fact] public void ConditionalOperator_11() { var source = @"class C { static void F(bool b, object x) { (b ? x : throw null!).ToString(); (b ? throw null! : x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ConditionalOperator_12() { var source = @"using System; class C { static void F(bool b) { (b ? throw new Exception() : throw new Exception()).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,10): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between '' and '' // (b ? throw new Exception() : throw new Exception()).ToString(); Diagnostic(ErrorCode.ERR_InvalidQM, "b ? throw new Exception() : throw new Exception()").WithArguments("", "").WithLocation(6, 10)); } [Fact] public void ConditionalOperator_13() { var source = @"class C { static bool F(object? x) { return true; } static void F1(bool c, bool b1, bool b2, object v1) { object x1; object y1; object? z1 = null; object? w1 = null; if (c ? b1 && F(x1 = v1) && F(z1 = v1) : b2 && F(y1 = v1) && F(w1 = v1)) { x1.ToString(); // unassigned (if) y1.ToString(); // unassigned (if) z1.ToString(); // may be null (if) w1.ToString(); // may be null (if) } else { x1.ToString(); // unassigned (no error) (else) y1.ToString(); // unassigned (no error) (else) z1.ToString(); // may be null (else) w1.ToString(); // may be null (else) } } static void F2(bool b1, bool b2, object v2) { object x2; object y2; object? z2 = null; object? w2 = null; if (true ? b1 && F(x2 = v2) && F(z2 = v2) : b2 && F(y2 = v2) && F(w2 = v2)) { x2.ToString(); // ok (if) y2.ToString(); // unassigned (if) z2.ToString(); // ok (if) w2.ToString(); // may be null (if) } else { x2.ToString(); // unassigned (else) y2.ToString(); // unassigned (no error) (else) z2.ToString(); // may be null (else) w2.ToString(); // may be null (else) } } static void F3(bool b1, bool b2, object v3) { object x3; object y3; object? z3 = null; object? w3 = null; if (false ? b1 && F(x3 = v3) && F(z3 = v3) : b2 && F(y3 = v3) && F(w3 = v3)) { x3.ToString(); // unassigned (if) y3.ToString(); // ok (if) z3.ToString(); // may be null (if) w3.ToString(); // ok (if) } else { x3.ToString(); // unassigned (no error) (else) y3.ToString(); // unassigned (else) z3.ToString(); // may be null (else) w3.ToString(); // may be null (else) } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): error CS0165: Use of unassigned local variable 'x1' // x1.ToString(); // unassigned (if) Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(15, 13), // (16,13): error CS0165: Use of unassigned local variable 'y1' // y1.ToString(); // unassigned (if) Diagnostic(ErrorCode.ERR_UseDefViolation, "y1").WithArguments("y1").WithLocation(16, 13), // (17,13): warning CS8602: Dereference of a possibly null reference. // z1.ToString(); // may be null (if) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(17, 13), // (18,13): warning CS8602: Dereference of a possibly null reference. // w1.ToString(); // may be null (if) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w1").WithLocation(18, 13), // (24,13): warning CS8602: Dereference of a possibly null reference. // z1.ToString(); // may be null (else) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(24, 13), // (25,13): warning CS8602: Dereference of a possibly null reference. // w1.ToString(); // may be null (else) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w1").WithLocation(25, 13), // (37,13): error CS0165: Use of unassigned local variable 'y2' // y2.ToString(); // unassigned (if) Diagnostic(ErrorCode.ERR_UseDefViolation, "y2").WithArguments("y2").WithLocation(37, 13), // (43,13): error CS0165: Use of unassigned local variable 'x2' // x2.ToString(); // unassigned (else) Diagnostic(ErrorCode.ERR_UseDefViolation, "x2").WithArguments("x2").WithLocation(43, 13), // (39,13): warning CS8602: Dereference of a possibly null reference. // w2.ToString(); // may be null (if) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(39, 13), // (45,13): warning CS8602: Dereference of a possibly null reference. // z2.ToString(); // may be null (else) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(45, 13), // (46,13): warning CS8602: Dereference of a possibly null reference. // w2.ToString(); // may be null (else) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(46, 13), // (57,13): error CS0165: Use of unassigned local variable 'x3' // x3.ToString(); // unassigned (if) Diagnostic(ErrorCode.ERR_UseDefViolation, "x3").WithArguments("x3").WithLocation(57, 13), // (65,13): error CS0165: Use of unassigned local variable 'y3' // y3.ToString(); // unassigned (else) Diagnostic(ErrorCode.ERR_UseDefViolation, "y3").WithArguments("y3").WithLocation(65, 13), // (59,13): warning CS8602: Dereference of a possibly null reference. // z3.ToString(); // may be null (if) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z3").WithLocation(59, 13), // (66,13): warning CS8602: Dereference of a possibly null reference. // z3.ToString(); // may be null (else) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z3").WithLocation(66, 13), // (67,13): warning CS8602: Dereference of a possibly null reference. // w3.ToString(); // may be null (else) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w3").WithLocation(67, 13)); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_14() { var source = @"interface I { T P { get; } } interface IIn { } interface IOut { T P { get; } } class C { static void F1(bool b, ref string? x1, ref string y1) { (b ? ref x1 : ref x1)/*T:string?*/.ToString(); // 1 (b ? ref x1 : ref y1)/*T:string?*/.ToString(); // 2, 3 (b ? ref y1 : ref x1)/*T:string?*/.ToString(); // 4, 5 (b ? ref y1 : ref y1)/*T:string!*/.ToString(); } static void F2(bool b, ref I x2, ref I y2) { (b ? ref x2 : ref x2)/*T:I!*/.P.ToString(); // 6 (b ? ref y2 : ref x2)/*T:I!*/.P.ToString(); // 7 (b ? ref x2 : ref y2)/*T:I!*/.P.ToString(); // 8, 9 (b ? ref y2 : ref y2)/*T:I!*/.P.ToString(); } static void F3(bool b, ref IIn x3, ref IIn y3) { (b ? ref x3 : ref x3)/*T:IIn!*/.ToString(); (b ? ref y3 : ref x3)/*T:IIn!*/.ToString(); // 10 (b ? ref x3 : ref y3)/*T:IIn!*/.ToString(); // 11 (b ? ref y3 : ref y3)/*T:IIn!*/.ToString(); } static void F4(bool b, ref IOut x4, ref IOut y4) { (b ? ref x4 : ref x4)/*T:IOut!*/.P.ToString(); // 12 (b ? ref y4 : ref x4)/*T:IOut!*/.P.ToString(); // 13 (b ? ref x4 : ref y4)/*T:IOut!*/.P.ToString(); // 14 (b ? ref y4 : ref y4)/*T:IOut!*/.P.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (8,10): warning CS8602: Possible dereference of a null reference. // (b ? ref x1 : ref x1)/*T:string?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref x1 : ref x1").WithLocation(8, 10), // (9,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // (b ? ref x1 : ref y1)/*T:string?*/.ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x1 : ref y1").WithArguments("string?", "string").WithLocation(9, 10), // (9,10): warning CS8602: Possible dereference of a null reference. // (b ? ref x1 : ref y1)/*T:string?*/.ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref x1 : ref y1").WithLocation(9, 10), // (10,10): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // (b ? ref y1 : ref x1)/*T:string?*/.ToString(); // 4, 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y1 : ref x1").WithArguments("string", "string?").WithLocation(10, 10), // (10,10): warning CS8602: Possible dereference of a null reference. // (b ? ref y1 : ref x1)/*T:string?*/.ToString(); // 4, 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref y1 : ref x1").WithLocation(10, 10), // (15,9): warning CS8602: Possible dereference of a null reference. // (b ? ref x2 : ref x2)/*T:I!*/.P.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b ? ref x2 : ref x2)/*T:I!*/.P").WithLocation(15, 9), // (16,10): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // (b ? ref y2 : ref x2)/*T:I!*/.P.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y2 : ref x2").WithArguments("I", "I").WithLocation(16, 10), // (17,10): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // (b ? ref x2 : ref y2)/*T:I!*/.P.ToString(); // 8, 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x2 : ref y2").WithArguments("I", "I").WithLocation(17, 10), // (23,10): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // (b ? ref y3 : ref x3)/*T:IIn!*/.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y3 : ref x3").WithArguments("IIn", "IIn").WithLocation(23, 10), // (24,10): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // (b ? ref x3 : ref y3)/*T:IIn!*/.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x3 : ref y3").WithArguments("IIn", "IIn").WithLocation(24, 10), // (29,9): warning CS8602: Possible dereference of a null reference. // (b ? ref x4 : ref x4)/*T:IOut!*/.P.ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b ? ref x4 : ref x4)/*T:IOut!*/.P").WithLocation(29, 9), // (30,10): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // (b ? ref y4 : ref x4)/*T:IOut!*/.P.ToString(); // 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y4 : ref x4").WithArguments("IOut", "IOut").WithLocation(30, 10), // (31,10): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // (b ? ref x4 : ref y4)/*T:IOut!*/.P.ToString(); // 14, 15 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x4 : ref y4").WithArguments("IOut", "IOut").WithLocation(31, 10)); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_WithLambdaConversions() { var source = @" using System; class C { Func D1(T t) => k => t; void M1(bool b, string? s) { _ = (b ? D1(s) : k => s) /*T:System.Func!*/; _ = (b ? k => s : D1(s)) /*T:System.Func!*/; _ = (true ? D1(s) : k => s) /*T:System.Func!*/; _ = (true ? k => s : D1(s)) /*T:System.Func!*/; // unexpected type _ = (false ? D1(s) : k => s) /*T:System.Func!*/; // unexpected type _ = (false ? k => s : D1(s)) /*T:System.Func!*/; _ = (b ? D1(s!) : k => s) /*T:System.Func!*/; // 1, unexpected type _ = (b ? k => s : D1(s!)) /*T:System.Func!*/; // 2, unexpected type _ = (true ? D1(s!) : k => s) /*T:System.Func!*/; // unexpected type _ = (true ? k => s : D1(s!)) /*T:System.Func!*/; // 3, unexpected type _ = (false ? D1(s!) : k => s) /*T:System.Func!*/; // 4, unexpected type _ = (false ? k => s : D1(s!)) /*T:System.Func!*/; // unexpected type _ = (b ? D1(true ? throw null! : s) : k => s) /*T:System.Func!*/; // 5, unexpected type _ = (b ? k => s : D1(true ? throw null! : s)) /*T:System.Func!*/; // 6, unexpected type _ = (true ? D1(true ? throw null! : s) : k => s) /*T:System.Func!*/; // unexpected type _ = (true ? k => s : D1(true ? throw null! : s)) /*T:System.Func!*/; // 7, unexpected type _ = (false ? D1(true ? throw null! : s) : k => s) /*T:System.Func!*/; // 8, unexpected type _ = (false ? k => s : D1(true ? throw null! : s)) /*T:System.Func!*/; // unexpected type } delegate T MyDelegate(bool b); ref MyDelegate D2(T t) => throw null!; void M(bool b, string? s) { _ = (b ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 9 _ = (b ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 10 _ = (true ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 11 _ = (true ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; _ = (false ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; _ = (false ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 12 } }"; // See https://github.com/dotnet/roslyn/issues/34392 // Best type inference involving lambda conversion should agree with method type inference // Missing diagnostics var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (36,14): warning CS8619: Nullability of reference types in value of type 'C.MyDelegate' doesn't match target type 'C.MyDelegate'. // _ = (b ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref D2(s) : ref D2(s!)").WithArguments("C.MyDelegate", "C.MyDelegate").WithLocation(36, 14), // (37,14): warning CS8619: Nullability of reference types in value of type 'C.MyDelegate' doesn't match target type 'C.MyDelegate'. // _ = (b ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref D2(s!) : ref D2(s)").WithArguments("C.MyDelegate", "C.MyDelegate").WithLocation(37, 14), // (38,14): warning CS8619: Nullability of reference types in value of type 'C.MyDelegate' doesn't match target type 'C.MyDelegate'. // _ = (true ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "true ? ref D2(s) : ref D2(s!)").WithArguments("C.MyDelegate", "C.MyDelegate").WithLocation(38, 14), // (41,14): warning CS8619: Nullability of reference types in value of type 'C.MyDelegate' doesn't match target type 'C.MyDelegate'. // _ = (false ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // unexpected type Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "false ? ref D2(s!) : ref D2(s)").WithArguments("C.MyDelegate", "C.MyDelegate").WithLocation(41, 14) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_WithUserDefinedConversion() { var source = @" class D { } class C { public static implicit operator D?(C c) => throw null!; static void M1(bool b, C c, D d) { _ = (b ? c : d) /*T:D?*/; _ = (b ? d : c) /*T:D?*/; _ = (true ? c : d) /*T:D?*/; _ = (true ? d : c) /*T:D!*/; _ = (false ? c : d) /*T:D!*/; _ = (false ? d : c) /*T:D?*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_NestedNullabilityMismatch() { var source = @" class C { static void M1(bool b, string s, string? s2) { (b ? ref Create(s, s2) : ref Create(s2, s)) /*T:C!*/ = null; (b ? ref Create(s2, s) : ref Create(s, s2)) /*T:C!*/ = null; } static ref C Create(U1 x, U2 y) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,10): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // (b ? ref Create(s, s2) : ref Create(s2, s)) /*T:C!*/ = null; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref Create(s, s2) : ref Create(s2, s)").WithArguments("C", "C").WithLocation(6, 10), // (6,80): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref Create(s, s2) : ref Create(s2, s)) /*T:C!*/ = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 80), // (7,10): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // (b ? ref Create(s2, s) : ref Create(s, s2)) /*T:C!*/ = null; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref Create(s2, s) : ref Create(s, s2)").WithArguments("C", "C").WithLocation(7, 10), // (7,80): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref Create(s2, s) : ref Create(s, s2)) /*T:C!*/ = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 80) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_WithAlteredStates() { var source = @" class C { static void F1(bool b, ref string? x1, ref string y1) { y1 = null; // 1 (b ? ref x1 : ref x1)/*T:string?*/.ToString(); // 2 (b ? ref x1 : ref y1)/*T:string?*/.ToString(); // 3, 4 (b ? ref y1 : ref x1)/*T:string?*/.ToString(); // 5, 6 (b ? ref y1 : ref y1)/*T:string?*/.ToString(); // 7 x1 = """"; y1 = """"; (b ? ref x1 : ref x1)/*T:string!*/.ToString(); (b ? ref x1 : ref y1)/*T:string!*/.ToString(); // 8 (b ? ref y1 : ref x1)/*T:string!*/.ToString(); // 9 (b ? ref y1 : ref y1)/*T:string!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // y1 = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 14), // (7,10): warning CS8602: Possible dereference of a null reference. // (b ? ref x1 : ref x1)/*T:string?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref x1 : ref x1").WithLocation(7, 10), // (8,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // (b ? ref x1 : ref y1)/*T:string?*/.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x1 : ref y1").WithArguments("string?", "string").WithLocation(8, 10), // (8,10): warning CS8602: Possible dereference of a null reference. // (b ? ref x1 : ref y1)/*T:string?*/.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref x1 : ref y1").WithLocation(8, 10), // (9,10): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // (b ? ref y1 : ref x1)/*T:string?*/.ToString(); // 5, 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y1 : ref x1").WithArguments("string", "string?").WithLocation(9, 10), // (9,10): warning CS8602: Possible dereference of a null reference. // (b ? ref y1 : ref x1)/*T:string?*/.ToString(); // 5, 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref y1 : ref x1").WithLocation(9, 10), // (10,10): warning CS8602: Possible dereference of a null reference. // (b ? ref y1 : ref y1)/*T:string?*/.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? ref y1 : ref y1").WithLocation(10, 10), // (15,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // (b ? ref x1 : ref y1)/*T:string!*/.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x1 : ref y1").WithArguments("string?", "string").WithLocation(15, 10), // (16,10): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // (b ? ref y1 : ref x1)/*T:string!*/.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y1 : ref x1").WithArguments("string", "string?").WithLocation(16, 10) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_WithUnreachable() { var source = @" class C { static void F1(bool b, string? x1, string y1) { ((b && false) ? x1 : x1)/*T:string?*/.ToString(); // 1 ((b && false) ? x1 : y1)/*T:string!*/.ToString(); ((b && false) ? y1 : x1)/*T:string?*/.ToString(); // 2 ((b && false) ? y1 : y1)/*T:string!*/.ToString(); ((b || true) ? x1 : x1)/*T:string?*/.ToString(); // 3 ((b || true) ? x1 : y1)/*T:string?*/.ToString(); // 4 ((b || true) ? y1 : x1)/*T:string!*/.ToString(); ((b || true) ? y1 : y1)/*T:string!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,10): warning CS8602: Possible dereference of a null reference. // ((b && false) ? x1 : x1)/*T:string?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b && false) ? x1 : x1").WithLocation(6, 10), // (8,10): warning CS8602: Possible dereference of a null reference. // ((b && false) ? y1 : x1)/*T:string?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b && false) ? y1 : x1").WithLocation(8, 10), // (11,10): warning CS8602: Possible dereference of a null reference. // ((b || true) ? x1 : x1)/*T:string?*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b || true) ? x1 : x1").WithLocation(11, 10), // (12,10): warning CS8602: Possible dereference of a null reference. // ((b || true) ? x1 : y1)/*T:string?*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b || true) ? x1 : y1").WithLocation(12, 10) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_SideEffectsInUnreachableBranch() { var source = @" class C { void M1(string? s, string? s2) { s = """"; (false ? ref M3(s = null) : ref s2) = null; s.ToString(); (true ? ref M3(s = null) : ref s2) = null; s.ToString(); // 1 } void M2(string? s, string? s2) { s = """"; (true ? ref s2 : ref M3(s = null)) = null; s.ToString(); (false ? ref s2 : ref M3(s = null)) = null; s.ToString(); // 2 } ref string? M3(string? x) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(10, 9), // (18,9): warning CS8602: Possible dereference of a null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 9)); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_WithReachableBranchThatThrows() { var source = @" class C { static void F1(bool b) { (b ? M1(false ? 1 : throw new System.Exception()) : M2(2))/*T:string!*/.ToString(); (b ? M1(1) : M2(false ? 2 : throw new System.Exception()))/*T:string?*/.ToString(); // 1 } static string? M1(int i) => throw null!; static string M2(int i) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (7,10): warning CS8602: Possible dereference of a null reference. // (b ? M1(1) : M2(false ? 2 : throw new System.Exception()))/*T:string?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? M1(1) : M2(false ? 2 : throw new System.Exception())").WithLocation(7, 10) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_EndNotReachable() { var source = @" class C { static void F1(bool b) { (true ? M1(false ? 1 : throw new System.Exception()) : M2(2)) /*T:string!*/.ToString(); (false ? M1(1) : M2(false ? 2 : throw new System.Exception())) /*T:string!*/.ToString(); } static string? M1(int i) => throw null!; static string M2(int i) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_WithReachableBranchThatThrows() { var source = @" class C { static void F1(bool b) { (b ? ref M1(false ? 1 : throw new System.Exception()) : ref M2(2)) /*T:string!*/ = null; // 1, 2 (b ? ref M1(1) : ref M2(false ? 2 : throw new System.Exception())) /*T:string?*/ = null; // 3, 4 } static ref string? M1(int i) => throw null!; static ref string M2(int i) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // (b ? ref M1(false ? 1 : throw new System.Exception()) : ref M2(2)) /*T:string!*/ = null; // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref M1(false ? 1 : throw new System.Exception()) : ref M2(2)").WithArguments("string?", "string").WithLocation(6, 10), // (6,92): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref M1(false ? 1 : throw new System.Exception()) : ref M2(2)) /*T:string!*/ = null; // 1, 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 92), // (7,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // (b ? ref M1(1) : ref M2(false ? 2 : throw new System.Exception())) /*T:string?*/ = null; // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref M1(1) : ref M2(false ? 2 : throw new System.Exception())").WithArguments("string?", "string").WithLocation(7, 10), // (7,92): warning CS8625: Cannot convert null literal to non-nullable reference type. // (b ? ref M1(1) : ref M2(false ? 2 : throw new System.Exception())) /*T:string?*/ = null; // 3, 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 92) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_EndNotReachable() { var source = @" class C { static void F1(bool b) { (true ? ref M1(false ? 1 : throw new System.Exception()) : ref M2(2)) /*T:string!*/ = null; (false ? ref M1(1) : ref M2(false ? 2 : throw new System.Exception())) /*T:string!*/ = null; } static ref string? M1(int i) => throw null!; static ref string M2(int i) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_WithUnreachable() { var source = @" class C { static void F1(bool b, ref string? x1, ref string y1) { ((b && false) ? ref x1 : ref x1)/*T:string?*/ = null; ((b && false) ? ref x1 : ref y1)/*T:string!*/ = null; // 1, 2 ((b && false) ? ref y1 : ref x1)/*T:string?*/ = null; // 3, 4 ((b && false) ? ref y1 : ref y1)/*T:string!*/ = null; // 5 ((b || true) ? ref x1 : ref x1)/*T:string?*/ = null; ((b || true) ? ref x1 : ref y1)/*T:string?*/ = null; // 6, 7 ((b || true) ? ref y1 : ref x1)/*T:string!*/ = null; // 8, 9 ((b || true) ? ref y1 : ref y1)/*T:string!*/ = null; // 10 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (7,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // ((b && false) ? ref x1 : ref y1)/*T:string!*/ = null; // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(b && false) ? ref x1 : ref y1").WithArguments("string?", "string").WithLocation(7, 10), // (7,57): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((b && false) ? ref x1 : ref y1)/*T:string!*/ = null; // 1, 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(7, 57), // (8,10): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // ((b && false) ? ref y1 : ref x1)/*T:string?*/ = null; // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(b && false) ? ref y1 : ref x1").WithArguments("string", "string?").WithLocation(8, 10), // (8,57): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((b && false) ? ref y1 : ref x1)/*T:string?*/ = null; // 3, 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 57), // (9,57): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((b && false) ? ref y1 : ref y1)/*T:string!*/ = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(9, 57), // (12,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // ((b || true) ? ref x1 : ref y1)/*T:string?*/ = null; // 6, 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(b || true) ? ref x1 : ref y1").WithArguments("string?", "string").WithLocation(12, 10), // (12,56): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((b || true) ? ref x1 : ref y1)/*T:string?*/ = null; // 6, 7 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 56), // (13,10): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // ((b || true) ? ref y1 : ref x1)/*T:string!*/ = null; // 8, 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(b || true) ? ref y1 : ref x1").WithArguments("string", "string?").WithLocation(13, 10), // (13,56): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((b || true) ? ref y1 : ref x1)/*T:string!*/ = null; // 8, 9 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 56), // (14,56): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((b || true) ? ref y1 : ref y1)/*T:string!*/ = null; // 10 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 56) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_WithError() { var source = @" class C { static void F1(bool b, ref string? x1) { (b ? ref x1 : ref error)/*T:!*/.ToString(); (b ? ref x1 : ref error)/*T:!*/.ToString(); (b ? ref error : ref x1)/*T:!*/.ToString(); (b ? ref error : ref error)/*T:!*/.ToString(); x1 = """"; (b ? ref x1 : ref error)/*T:!*/.ToString(); (b ? ref x1 : ref error)/*T:!*/.ToString(); (b ? ref error : ref x1)/*T:!*/.ToString(); (b ? ref error : ref error)/*T:!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref x1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(6, 27), // (7,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref x1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(7, 27), // (8,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref x1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(8, 18), // (9,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(9, 18), // (9,30): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(9, 30), // (12,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref x1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(12, 27), // (13,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref x1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(13, 27), // (14,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref x1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(14, 18), // (15,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(15, 18), // (15,30): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(15, 30) ); } [Fact] [WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_Ref_WithError_Nested() { var source = @" class C { static void F1(bool b, ref C x1, ref C y1) { (b ? ref x1 : ref error)/*T:!*/.ToString(); (b ? ref x1 : ref error)/*T:!*/.ToString(); (b ? ref error : ref x1)/*T:!*/.ToString(); (b ? ref error : ref error)/*T:!*/.ToString(); (b ? ref y1 : ref error)/*T:!*/.ToString(); (b ? ref y1 : ref error)/*T:!*/.ToString(); (b ? ref error : ref y1)/*T:!*/.ToString(); (b ? ref error : ref error)/*T:!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref x1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(6, 27), // (7,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref x1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(7, 27), // (8,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref x1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(8, 18), // (9,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(9, 18), // (9,30): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(9, 30), // (11,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref y1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(11, 27), // (12,27): error CS0103: The name 'error' does not exist in the current context // (b ? ref y1 : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(12, 27), // (13,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref y1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(13, 18), // (14,18): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(14, 18), // (14,30): error CS0103: The name 'error' does not exist in the current context // (b ? ref error : ref error)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_NameNotInContext, "error").WithArguments("error").WithLocation(14, 30) ); } [Fact] public void ConditionalOperator_15() { // We likely shouldn't be warning on the x[0] access, as code is an error. However, we currently do // because of fallout from https://github.com/dotnet/roslyn/issues/34158: when we calculate the // type of new[] { x }, the type of the BoundLocal x is ErrorType var, but the type of the local // symbol is ErrorType var[]. VisitLocal prefers the type of the BoundLocal, and so the // new[] { x } expression is calculcated to have a final type of ErrorType var[]. The default is // target typed to ErrorType var[] as well, and the logic in VisitConditionalOperator therefore // uses that type as the final type of the expression. This calculation succeeded, so that result // is stored as the current nullability of x, causing us to warn on the subsequent line. var source = @"class Program { static void F(bool b) { var x = b ? new[] { x } : default; x[0].ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,29): error CS0841: Cannot use local variable 'x' before it is declared // var x = b ? new[] { x } : default; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x").WithArguments("x").WithLocation(5, 29), // (5,29): error CS0165: Use of unassigned local variable 'x' // var x = b ? new[] { x } : default; Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(5, 29), // (6,9): warning CS8602: Dereference of a possibly null reference. // x[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9)); } [Fact] public void ConditionalOperator_16() { var source = @"class Program { static bool F(object? x) { return true; } static void F1(bool b, bool c, object x1, object? y1) { if (b ? c && F(x1 = y1) : true) // 1 { x1.ToString(); // 2 } } static void F2(bool b, bool c, object x2, object? y2) { if (b ? true : c && F(x2 = y2)) // 3 { x2.ToString(); // 4 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,29): warning CS8600: Converting null literal or possible null value to non-nullable type. // if (b ? c && F(x1 = y1) : true) // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(9, 29), // (11,13): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(11, 13), // (16,36): warning CS8600: Converting null literal or possible null value to non-nullable type. // if (b ? true : c && F(x2 = y2)) // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2").WithLocation(16, 36), // (18,13): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(18, 13)); } [Fact] public void ConditionalOperator_17() { var source = @"class Program { static void F(bool x, bool y, bool z, bool? w) { object o; o = x ? y && z : w; // 1 o = true ? y && z : w; o = false ? w : y && z; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = x ? y && z : w; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x ? y && z : w").WithLocation(6, 13)); } [Fact] public void ConditionalOperator_TopLevelNullability() { var source = @"class C { static void F(bool b, object? x, object y) { object? o; o = (b ? x : x)/*T:object?*/; o = (b ? x : y)/*T:object?*/; o = (b ? y : x)/*T:object?*/; o = (b ? y : y)/*T:object!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] [Fact] public void ConditionalOperator_NestedNullability_Invariant() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F(bool b, B x, B y) { var z = A.F/*T:B!*/; object o; o = (b ? x : x)/*T:B!*/; o = (b ? x : y)/*T:B!*/; // 1 o = (b ? x : z)/*T:B!*/; o = (b ? y : x)/*T:B!*/; // 2 o = (b ? y : y)/*T:B!*/; o = (b ? y : z)/*T:B!*/; o = (b ? z : x)/*T:B!*/; o = (b ? z : y)/*T:B!*/; o = (b ? z : z)/*T:B!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,18): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (b ? x : y)/*T:B!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(8, 18), // (10,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (b ? y : x)/*T:B!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(10, 22) ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void ConditionalOperator_NestedNullability_Variant() { var source0 = @"public class A { public static I F; public static IIn FIn; public static IOut FOut; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F1(bool b, I x, I y) { var z = A.F/*T:I!*/; object o; o = (b ? x : x)/*T:I!*/; o = (b ? x : y)/*T:I!*/; // 1 o = (b ? x : z)/*T:I!*/; o = (b ? y : x)/*T:I!*/; // 2 o = (b ? y : y)/*T:I!*/; o = (b ? y : z)/*T:I!*/; o = (b ? z : x)/*T:I!*/; o = (b ? z : y)/*T:I!*/; o = (b ? z : z)/*T:I!*/; } static void F2(bool b, IIn x, IIn y) { var z = A.FIn/*T:IIn!*/; object o; o = (b ? x : x)/*T:IIn!*/; o = (b ? x : y)/*T:IIn!*/; o = (b ? x : z)/*T:IIn!*/; o = (b ? y : x)/*T:IIn!*/; o = (b ? y : y)/*T:IIn!*/; o = (b ? y : z)/*T:IIn!*/; o = (b ? z : x)/*T:IIn!*/; o = (b ? z : y)/*T:IIn!*/; o = (b ? z : z)/*T:IIn!*/; } static void F3(bool b, IOut x, IOut y) { var z = A.FOut/*T:IOut!*/; object o; o = (b ? x : x)/*T:IOut!*/; o = (b ? x : y)/*T:IOut!*/; o = (b ? x : z)/*T:IOut!*/; o = (b ? y : x)/*T:IOut!*/; o = (b ? y : y)/*T:IOut!*/; o = (b ? y : z)/*T:IOut!*/; o = (b ? z : x)/*T:IOut!*/; o = (b ? z : y)/*T:IOut!*/; o = (b ? z : z)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,22): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // o = (b ? x : y)/*T:I!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(8, 22), // (10,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // o = (b ? y : x)/*T:I!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(10, 18) ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void ConditionalOperator_NestedNullability_VariantAndInvariant() { var source0 = @"public class A { public static IIn F1; public static IOut F2; } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F1(bool b, IIn x1, IIn y1) { var z1 = A.F1/*T:IIn!*/; object o; o = (b ? x1 : x1)/*T:IIn!*/; o = (b ? x1 : y1)/*T:IIn!*/; // 1 o = (b ? x1 : z1)/*T:IIn!*/; o = (b ? y1 : x1)/*T:IIn!*/; // 2 o = (b ? y1 : y1)/*T:IIn!*/; o = (b ? y1 : z1)/*T:IIn!*/; o = (b ? z1 : x1)/*T:IIn!*/; o = (b ? z1 : y1)/*T:IIn!*/; o = (b ? z1 : z1)/*T:IIn!*/; } static void F2(bool b, IOut x2, IOut y2) { var z2 = A.F2/*T:IOut!*/; object o; o = (b ? x2 : x2)/*T:IOut!*/; o = (b ? x2 : y2)/*T:IOut!*/; // 3 o = (b ? x2 : z2)/*T:IOut!*/; o = (b ? y2 : x2)/*T:IOut!*/; // 4 o = (b ? y2 : y2)/*T:IOut!*/; o = (b ? y2 : z2)/*T:IOut!*/; o = (b ? z2 : x2)/*T:IOut!*/; o = (b ? z2 : y2)/*T:IOut!*/; o = (b ? z2 : z2)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,23): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // o = (b ? x1 : y1)/*T:IIn!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(8, 23), // (10,18): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // o = (b ? y1 : x1)/*T:IIn!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(10, 18), // (22,23): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // o = (b ? x2 : y2)/*T:IOut!*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("IOut", "IOut").WithLocation(22, 23), // (24,18): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // o = (b ? y2 : x2)/*T:IOut!*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("IOut", "IOut").WithLocation(24, 18) ); comp.VerifyTypes(); } [Fact] public void ConditionalOperator_NestedNullability_Tuples() { var source0 = @"public class A { public static I F; } public interface I { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @" class C { static void F1(bool b, object x1, object? y1) { object o; o = (b ? (x1, x1) : (x1, y1))/*T:(object!, object?)*/; o = (b ? (x1, y1) : (y1, y1))/*T:(object?, object?)*/; } static void F2(bool b, I x2, I y2) { var z2 = A.F/*T:I!*/; object o; o = (b ? (x2, x2) : (x2, y2))/*T:(I!, I!)*/; o = (b ? (z2, x2) : (x2, x2))/*T:(I!, I!)*/; o = (b ? (y2, y2) : (y2, z2))/*T:(I!, I!)*/; o = (b ? (x2, y2) : (y2, y2))/*T:(I!, I!)*/; o = (b ? (z2, z2) : (z2, x2))/*T:(I!, I!)*/; o = (b ? (y2, z2) : (z2, z2))/*T:(I!, I!)*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (14,29): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. // o = (b ? (x2, x2) : (x2, y2))/*T:(I!, I!)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(14, 29), // (17,29): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. // o = (b ? (x2, y2) : (y2, y2))/*T:(I!, I!)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(17, 29) ); comp.VerifyTypes(); } [WorkItem(30432, "https://github.com/dotnet/roslyn/issues/30432")] [Fact] public void ConditionalOperator_TopLevelNullability_Ref() { var source0 = @"public class A { public static object F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F(bool b, object? x, object y) { ref var xx = ref b ? ref x : ref x; ref var xy = ref b ? ref x : ref y; // 1 ref var xz = ref b ? ref x : ref A.F; ref var yx = ref b ? ref y : ref x; // 2 ref var yy = ref b ? ref y : ref y; ref var yz = ref b ? ref y : ref A.F; ref var zx = ref b ? ref A.F : ref x; ref var zy = ref b ? ref A.F : ref y; ref var zz = ref b ? ref A.F : ref A.F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (6,26): warning CS8619: Nullability of reference types in value of type 'object?' doesn't match target type 'object'. // ref var xy = ref b ? ref x : ref y; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x : ref y").WithArguments("object?", "object").WithLocation(6, 26), // (8,26): warning CS8619: Nullability of reference types in value of type 'object' doesn't match target type 'object?'. // ref var yx = ref b ? ref y : ref x; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y : ref x").WithArguments("object", "object?").WithLocation(8, 26) ); } [WorkItem(30432, "https://github.com/dotnet/roslyn/issues/30432")] [Fact] public void ConditionalOperator_NestedNullability_Ref() { var source0 = @"public class A { public static I IOblivious; public static IIn IInOblivious; public static IOut IOutOblivious; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F1(bool b, I x1, I y1) { var z1 = A.IOblivious/*T:I!*/; ref var xx = ref b ? ref x1 : ref x1; ref var xy = ref b ? ref x1 : ref y1; // 1 ref var xz = ref b ? ref x1 : ref z1; ref var yx = ref b ? ref y1 : ref x1; // 2 ref var yy = ref b ? ref y1 : ref y1; ref var yz = ref b ? ref y1 : ref z1; ref var zx = ref b ? ref z1 : ref x1; ref var zy = ref b ? ref z1 : ref y1; ref var zz = ref b ? ref z1 : ref z1; } static void F2(bool b, IIn x2, IIn y2) { var z2 = A.IInOblivious/*T:IIn!*/; ref var xx = ref b ? ref x2 : ref x2; ref var xy = ref b ? ref x2 : ref y2; // 3 ref var xz = ref b ? ref x2 : ref z2; ref var yx = ref b ? ref y2 : ref x2; // 4 ref var yy = ref b ? ref y2 : ref y2; ref var yz = ref b ? ref y2 : ref z2; ref var zx = ref b ? ref z2 : ref x2; ref var zy = ref b ? ref z2 : ref y2; ref var zz = ref b ? ref z2 : ref z2; } static void F3(bool b, IOut x3, IOut y3) { var z3 = A.IOutOblivious/*T:IOut!*/; ref var xx = ref b ? ref x3 : ref x3; ref var xy = ref b ? ref x3 : ref y3; // 5 ref var xz = ref b ? ref x3 : ref z3; ref var yx = ref b ? ref y3 : ref x3; // 6 ref var yy = ref b ? ref y3 : ref y3; ref var yz = ref b ? ref y3 : ref z3; ref var zx = ref b ? ref z3 : ref x3; ref var zy = ref b ? ref z3 : ref y3; ref var zz = ref b ? ref z3 : ref z3; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (7,26): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // ref var xy = ref b ? ref x1 : ref y1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x1 : ref y1").WithArguments("I", "I").WithLocation(7, 26), // (9,26): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // ref var yx = ref b ? ref y1 : ref x1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y1 : ref x1").WithArguments("I", "I").WithLocation(9, 26), // (20,26): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // ref var xy = ref b ? ref x2 : ref y2; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x2 : ref y2").WithArguments("IIn", "IIn").WithLocation(20, 26), // (22,26): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // ref var yx = ref b ? ref y2 : ref x2; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y2 : ref x2").WithArguments("IIn", "IIn").WithLocation(22, 26), // (33,26): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // ref var xy = ref b ? ref x3 : ref y3; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref x3 : ref y3").WithArguments("IOut", "IOut").WithLocation(33, 26), // (35,26): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // ref var yx = ref b ? ref y3 : ref x3; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b ? ref y3 : ref x3").WithArguments("IOut", "IOut").WithLocation(35, 26) ); comp.VerifyTypes(); } [Fact, WorkItem(33664, "https://github.com/dotnet/roslyn/issues/33664")] public void ConditionalOperator_AssigningToRefConditional() { var source0 = @"public class A { public static string F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var comp = CreateCompilation(@" class C { void M(bool c, ref string x, ref string? y) { (c ? ref x : ref y) = null; // 1, 2 } void M2(bool c, ref string x, ref string? y) { (c ? ref y : ref x) = null; // 3, 4 } void M3(bool c, ref string x, ref string? y) { (c ? ref x : ref A.F) = null; // 5 (c ? ref y : ref A.F) = null; } void M4(bool c, ref string x, ref string? y) { (c ? ref A.F : ref x) = null; // 6 (c ? ref A.F : ref y) = null; } }", options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (6,10): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // (c ? ref x : ref y) = null; // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? ref x : ref y").WithArguments("string", "string?").WithLocation(6, 10), // (6,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // (c ? ref x : ref y) = null; // 1, 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 31), // (10,10): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // (c ? ref y : ref x) = null; // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? ref y : ref x").WithArguments("string?", "string").WithLocation(10, 10), // (10,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // (c ? ref y : ref x) = null; // 3, 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 31), // (14,33): warning CS8625: Cannot convert null literal to non-nullable reference type. // (c ? ref x : ref A.F) = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 33), // (19,33): warning CS8625: Cannot convert null literal to non-nullable reference type. // (c ? ref A.F : ref x) = null; // 6 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 33) ); } [Fact] public void IdentityConversion_ConditionalOperator() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(bool c, I x, I y) { I a; a = c ? x : y; a = false ? x : y; a = true ? x : y; // ok I b; b = c ? x : y; b = false ? x : y; b = true ? x : y; } static void F(bool c, IIn x, IIn y) { IIn a; a = c ? x : y; a = false ? x : y; a = true ? x : y; IIn b; b = c ? x : y; b = false ? x : y; b = true ? x : y; } static void F(bool c, IOut x, IOut y) { IOut a; a = c ? x : y; a = false ? x : y; a = true ? x : y; IOut b; b = c ? x : y; b = false ? x : y; b = true ? x : y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,21): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // a = c ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(9, 21), // (10,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // a = false ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(10, 25), // (13,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // b = c ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x : y").WithArguments("I", "I").WithLocation(13, 13), // (13,21): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // b = c ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(13, 21), // (14,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // b = false ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "false ? x : y").WithArguments("I", "I").WithLocation(14, 13), // (14,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // b = false ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(14, 25), // (15,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // b = true ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "true ? x : y").WithArguments("I", "I").WithLocation(15, 13), // (24,13): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // b = c ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x : y").WithArguments("IIn", "IIn").WithLocation(24, 13), // (25,13): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // b = false ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "false ? x : y").WithArguments("IIn", "IIn").WithLocation(25, 13), // (26,13): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // b = true ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "true ? x : y").WithArguments("IIn", "IIn").WithLocation(26, 13), // (31,13): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // a = c ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x : y").WithArguments("IOut", "IOut").WithLocation(31, 13), // (32,13): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // a = false ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "false ? x : y").WithArguments("IOut", "IOut").WithLocation(32, 13), // (33,13): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // a = true ? x : y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "true ? x : y").WithArguments("IOut", "IOut").WithLocation(33, 13)); } [Fact] public void NullCoalescingOperator_01() { var source = @"class C { static void F(object? x, object? y) { var z = x ?? y; z.ToString(); if (y == null) return; var w = x ?? y; w.ToString(); var v = null ?? x; v.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(6, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // v.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v").WithLocation(11, 9)); } [Fact] public void NullCoalescingOperator_02() { var source = @"class C { static void F(int i, object? x, object? y) { switch (i) { case 1: (x ?? y).ToString(); // 1 break; case 2: if (y != null) (x ?? y).ToString(); break; case 3: if (y != null) (y ?? x).ToString(); // 2 break; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,18): warning CS8602: Dereference of a possibly null reference. // (x ?? y).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x ?? y").WithLocation(8, 18), // (14,33): warning CS8602: Dereference of a possibly null reference. // if (y != null) (y ?? x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(14, 33) ); } [Fact] public void NullCoalescingOperator_03() { var source = @"class C { static void F(object x, object? y) { (null ?? null).ToString(); (null ?? x).ToString(); (null ?? y).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,10): error CS0019: Operator '??' cannot be applied to operands of type '' and '' // (null ?? null).ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "null ?? null").WithArguments("??", "", "").WithLocation(5, 10), // (7,10): warning CS8602: Dereference of a possibly null reference. // (null ?? y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "null ?? y").WithLocation(7, 10)); } [Fact] public void NullCoalescingOperator_04() { var source = @"class C { static void F(string x, string? y) { ("""" ?? x).ToString(); ("""" ?? y).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); } [Fact] public void NullCoalescingOperator_05() { var source0 = @"public class A { } public class B { } public class UnknownNull { public A A; public B B; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source1 = @"public class MaybeNull { public A? A; public B? B; } public class NotNull { public A A = new A(); public B B = new B(); }"; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp1.VerifyDiagnostics(); var ref1 = comp1.EmitToImageReference(); var source = @"class C { static void F1(UnknownNull x1, UnknownNull y1) { (x1.A ?? y1.B)/*T:!*/.ToString(); } static void F2(UnknownNull x2, MaybeNull y2) { (x2.A ?? y2.B)/*T:!*/.ToString(); } static void F3(MaybeNull x3, UnknownNull y3) { (x3.A ?? y3.B)/*T:!*/.ToString(); } static void F4(MaybeNull x4, MaybeNull y4) { (x4.A ?? y4.B)/*T:!*/.ToString(); } static void F5(UnknownNull x5, NotNull y5) { (x5.A ?? y5.B)/*T:!*/.ToString(); } static void F6(NotNull x6, UnknownNull y6) { (x6.A ?? y6.B)/*T:!*/.ToString(); } static void F7(MaybeNull x7, NotNull y7) { (x7.A ?? y7.B)/*T:!*/.ToString(); } static void F8(NotNull x8, MaybeNull y8) { (x8.A ?? y8.B)/*T:!*/.ToString(); } static void F9(NotNull x9, NotNull y9) { (x9.A ?? y9.B)/*T:!*/.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0, ref1 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (5,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x1.A ?? y1.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x1.A ?? y1.B").WithArguments("??", "A", "B").WithLocation(5, 10), // (9,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x2.A ?? y2.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x2.A ?? y2.B").WithArguments("??", "A", "B").WithLocation(9, 10), // (13,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x3.A ?? y3.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x3.A ?? y3.B").WithArguments("??", "A", "B").WithLocation(13, 10), // (17,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x4.A ?? y4.B)/*T:?*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x4.A ?? y4.B").WithArguments("??", "A", "B").WithLocation(17, 10), // (21,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x5.A ?? y5.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x5.A ?? y5.B").WithArguments("??", "A", "B").WithLocation(21, 10), // (25,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x6.A ?? y6.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x6.A ?? y6.B").WithArguments("??", "A", "B").WithLocation(25, 10), // (29,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x7.A ?? y7.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x7.A ?? y7.B").WithArguments("??", "A", "B").WithLocation(29, 10), // (33,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x8.A ?? y8.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x8.A ?? y8.B").WithArguments("??", "A", "B").WithLocation(33, 10), // (37,10): error CS0019: Operator '??' cannot be applied to operands of type 'A' and 'B' // (x9.A ?? y9.B)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x9.A ?? y9.B").WithArguments("??", "A", "B").WithLocation(37, 10) ); } [Fact] public void NullCoalescingOperator_06() { var source = @"class C { static void F1(int i, C x1, Unknown? y1) { switch (i) { case 1: (x1 ?? y1)/*T:!*/.ToString(); break; case 2: (y1 ?? x1)/*T:!*/.ToString(); break; case 3: (null ?? y1)/*T:Unknown?*/.ToString(); break; case 4: (y1 ?? null)/*T:Unknown!*/.ToString(); break; } } static void F2(int i, C? x2, Unknown y2) { switch (i) { case 1: (x2 ?? y2)/*T:!*/.ToString(); break; case 2: (y2 ?? x2)/*T:!*/.ToString(); break; case 3: (null ?? y2)/*T:!*/.ToString(); break; case 4: (y2 ?? null)/*T:!*/.ToString(); break; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // Note: Unknown type is treated as a value type comp.VerifyTypes(); comp.VerifyDiagnostics( // (3,33): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F1(int i, C x1, Unknown? y1) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 33), // (21,34): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F2(int i, C? x2, Unknown y2) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(21, 34), // (8,18): error CS0019: Operator '??' cannot be applied to operands of type 'C' and 'Unknown?' // (x1 ?? y1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "x1 ?? y1").WithArguments("??", "C", "Unknown?").WithLocation(8, 18), // (11,18): error CS0019: Operator '??' cannot be applied to operands of type 'Unknown?' and 'C' // (y1 ?? x1)/*T:!*/.ToString(); Diagnostic(ErrorCode.ERR_BadBinaryOps, "y1 ?? x1").WithArguments("??", "Unknown?", "C").WithLocation(11, 18)); } [Fact] public void NullCoalescingOperator_07() { var source = @"class C { static void F(object? o, object[]? a, object?[]? b) { if (o == null) { var c = new[] { o }; (a ?? c)[0].ToString(); (b ?? c)[0].ToString(); } else { var c = new[] { o }; (a ?? c)[0].ToString(); (b ?? c)[0].ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // (a ?? c)[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(a ?? c)[0]").WithLocation(8, 13), // (9,13): warning CS8602: Dereference of a possibly null reference. // (b ?? c)[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b ?? c)[0]").WithLocation(9, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // (b ?? c)[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b ?? c)[0]").WithLocation(15, 13)); } [Fact] public void NullCoalescingOperator_08() { var source = @"interface I { } class C { static object? F((I, I)? x, (I, I)? y) { return x ?? y; } static object F((I, I)? x, (I, I) y) { return x ?? y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,21): warning CS8619: Nullability of reference types in value of type '(I, I)?' doesn't match target type '(I, I)?'. // return x ?? y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("(I, I)?", "(I, I)?").WithLocation(6, 21), // (10,21): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. // return x ?? y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("(I, I)", "(I, I)").WithLocation(10, 21)); } [Fact] public void IdentityConversion_NullCoalescingOperator_01() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F1(I? x1, I y1) { I z1 = x1 ?? y1; I w1 = y1 ?? x1; } static void F2(IIn? x2, IIn y2) { IIn z2 = x2 ?? y2; IIn w2 = y2 ?? x2; } static void F3(IOut? x3, IOut y3) { IOut z3 = x3 ?? y3; IOut w3 = y3 ?? x3; } static void F4(IIn? x4, IIn y4) { IIn z4; z4 = ((IIn)x4) ?? y4; z4 = x4 ?? (IIn)y4; } static void F5(IIn? x5, IIn y5) { IIn z5; z5 = ((IIn)x5) ?? y5; z5 = x5 ?? (IIn)y5; } static void F6(IOut? x6, IOut y6) { IOut z6; z6 = ((IOut)x6) ?? y6; z6 = x6 ?? (IOut)y6; } static void F7(IOut? x7, IOut y7) { IOut z7; z7 = ((IOut)x7) ?? y7; z7 = x7 ?? (IOut)y7; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,30): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // I z1 = x1 ?? y1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("I", "I").WithLocation(8, 30), // (9,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // I w1 = y1 ?? x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1 ?? x1").WithLocation(9, 25), // (9,31): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // I w1 = y1 ?? x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I", "I").WithLocation(9, 31), // (14,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // IIn w2 = y2 ?? x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2 ?? x2").WithLocation(14, 27), // (14,27): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // IIn w2 = y2 ?? x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2 ?? x2").WithArguments("IIn", "IIn").WithLocation(14, 27), // (18,27): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // IOut z3 = x3 ?? y3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3 ?? y3").WithArguments("IOut", "IOut").WithLocation(18, 27), // (19,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // IOut w3 = y3 ?? x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y3 ?? x3").WithLocation(19, 28), // (24,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // z4 = ((IIn)x4) ?? y4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IIn)x4").WithLocation(24, 15), // (30,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // z5 = ((IIn)x5) ?? y5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IIn)x5").WithLocation(30, 15), // (36,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // z6 = ((IOut)x6) ?? y6; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IOut)x6").WithLocation(36, 15), // (42,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // z7 = ((IOut)x7) ?? y7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IOut)x7").WithLocation(42, 15)); } [Fact] public void IdentityConversion_NullCoalescingOperator_02() { // F1's types are incorrect. See https://github.com/dotnet/roslyn/issues/35012 var source = @"interface IIn { } interface IOut { } class C { static IIn? FIn(T x) { return null; } static IOut? FOut(T x) { return null; } static void FIn(IIn? x) { } static T FOut(IOut? x) { throw new System.Exception(); } static void F1(IIn? x1, IIn? y1) { FIn((x1 ?? y1)/*T:IIn?*/); FIn((y1 ?? x1)/*T:IIn?*/); } static void F2(IOut? x2, IOut? y2) { FOut((x2 ?? y2)/*T:IOut?*/).ToString(); FOut((y2 ?? x2)/*T:IOut?*/).ToString(); } static void F3(object? x3, object? y3) { FIn((FIn(x3) ?? FIn(y3))/*T:IIn?*/); // A if (x3 == null) return; FIn((FIn(x3) ?? FIn(y3))/*T:IIn?*/); // B FIn((FIn(y3) ?? FIn(x3))/*T:IIn?*/); // C if (y3 == null) return; FIn((FIn(x3) ?? FIn(y3))/*T:IIn?*/); // D } static void F4(object? x4, object? y4) { FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/).ToString(); // A if (x4 == null) return; FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/).ToString(); // B FOut((FOut(y4) ?? FOut(x4))/*T:IOut?*/).ToString(); // C if (y4 == null) return; FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/).ToString(); // D } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (22,14): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'void C.FIn(IIn? x)'. // FIn((x1 ?? y1)/*T:IIn?*/); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1 ?? y1").WithArguments("IIn", "IIn", "x", "void C.FIn(IIn? x)").WithLocation(22, 14), // (23,14): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'void C.FIn(IIn? x)'. // FIn((y1 ?? x1)/*T:IIn?*/); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1 ?? x1").WithArguments("IIn", "IIn", "x", "void C.FIn(IIn? x)").WithLocation(23, 14), // (27,9): warning CS8602: Dereference of a possibly null reference. // FOut((x2 ?? y2)/*T:IOut?*/).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "FOut((x2 ?? y2)/*T:IOut?*/)").WithLocation(27, 9), // (28,9): warning CS8602: Dereference of a possibly null reference. // FOut((y2 ?? x2)/*T:IOut?*/).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "FOut((y2 ?? x2)/*T:IOut?*/)").WithLocation(28, 9), // (34,14): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'void C.FIn(IIn? x)'. // FIn((FIn(x3) ?? FIn(y3))/*T:IIn?*/); // B Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "FIn(x3) ?? FIn(y3)").WithArguments("IIn", "IIn", "x", "void C.FIn(IIn? x)").WithLocation(34, 14), // (35,14): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'void C.FIn(IIn? x)'. // FIn((FIn(y3) ?? FIn(x3))/*T:IIn?*/); // C Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "FIn(y3) ?? FIn(x3)").WithArguments("IIn", "IIn", "x", "void C.FIn(IIn? x)").WithLocation(35, 14), // (37,14): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'void C.FIn(IIn? x)'. // FIn((FIn(x3) ?? FIn(y3))/*T:IIn?*/); // D Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "FIn(x3) ?? FIn(y3)").WithArguments("IIn", "IIn", "x", "void C.FIn(IIn? x)").WithLocation(37, 14), // (41,9): warning CS8602: Dereference of a possibly null reference. // FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/).ToString(); // A Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/)").WithLocation(41, 9), // (43,9): warning CS8602: Dereference of a possibly null reference. // FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/).ToString(); // B Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "FOut((FOut(x4) ?? FOut(y4))/*T:IOut?*/)").WithLocation(43, 9), // (44,9): warning CS8602: Dereference of a possibly null reference. // FOut((FOut(y4) ?? FOut(x4))/*T:IOut?*/).ToString(); // C Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "FOut((FOut(y4) ?? FOut(x4))/*T:IOut?*/)").WithLocation(44, 9)); } [Fact] public void IdentityConversion_NullCoalescingOperator_03() { var source = @"class C { static void F((object?, object?)? x, (object, object) y) { (x ?? y).Item1.ToString(); } static void G((object, object)? x, (object?, object?) y) { (x ?? y).Item1.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // (x ?? y).Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x ?? y).Item1").WithLocation(5, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // (x ?? y).Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x ?? y).Item1").WithLocation(9, 9)); } [Fact] public void IdentityConversion_NullCoalescingOperator_04() { var source = @"#pragma warning disable 0649 struct A { public static implicit operator B(A a) => default; } struct B { internal T F; } class C { static void F1(A? x1, B y1) { (x1 ?? y1)/*T:B*/.F.ToString(); } static void F2(A? x2, B y2) { (x2 ?? y2)/*T:B*/.F.ToString(); } static void F3(A x3, B? y3) { (y3 ?? x3)/*T:B*/.F.ToString(); } static void F4(A x4, B? y4) { (y4 ?? x4)/*T:B*/.F.ToString(); } static void F5(A? x5, B? y5) { (x5 ?? y5)/*T:B?*/.Value.F.ToString(); (y5 ?? x5)/*T:B?*/.Value.F.ToString(); } static void F6(A? x6, B? y6) { (x6 ?? y6)/*T:B?*/.Value.F.ToString(); (y6 ?? x6)/*T:B?*/.Value.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (14,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // (x1 ?? y1)/*T:B*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("A", "B").WithLocation(14, 10), // (14,9): warning CS8602: Dereference of a possibly null reference. // (x1 ?? y1)/*T:B*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x1 ?? y1)/*T:B*/.F").WithLocation(14, 9), // (18,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // (x2 ?? y2)/*T:B*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("A", "B").WithLocation(18, 10), // (22,16): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // (y3 ?? x3)/*T:B*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("B", "B").WithLocation(22, 16), // (22,9): warning CS8602: Dereference of a possibly null reference. // (y3 ?? x3)/*T:B*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y3 ?? x3)/*T:B*/.F").WithLocation(22, 9), // (26,16): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // (y4 ?? x4)/*T:B*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x4").WithArguments("B", "B").WithLocation(26, 16), // (30,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B?'. // (x5 ?? y5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x5").WithArguments("A", "B?").WithLocation(30, 10), // (30,10): warning CS8629: Nullable value type may be null. // (x5 ?? y5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x5 ?? y5").WithLocation(30, 10), // (30,9): warning CS8602: Dereference of a possibly null reference. // (x5 ?? y5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x5 ?? y5)/*T:B?*/.Value.F").WithLocation(30, 9), // (31,16): warning CS8619: Nullability of reference types in value of type 'B?' doesn't match target type 'B?'. // (y5 ?? x5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x5").WithArguments("B?", "B?").WithLocation(31, 16), // (31,10): warning CS8629: Nullable value type may be null. // (y5 ?? x5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y5 ?? x5").WithLocation(31, 10), // (31,9): warning CS8602: Dereference of a possibly null reference. // (y5 ?? x5)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y5 ?? x5)/*T:B?*/.Value.F").WithLocation(31, 9), // (35,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B?'. // (x6 ?? y6)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x6").WithArguments("A", "B?").WithLocation(35, 10), // (35,10): warning CS8629: Nullable value type may be null. // (x6 ?? y6)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x6 ?? y6").WithLocation(35, 10), // (36,16): warning CS8619: Nullability of reference types in value of type 'B?' doesn't match target type 'B?'. // (y6 ?? x6)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x6").WithArguments("B?", "B?").WithLocation(36, 16), // (36,10): warning CS8629: Nullable value type may be null. // (y6 ?? x6)/*T:B?*/.Value.F.ToString(); Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y6 ?? x6").WithLocation(36, 10) ); } [Fact] [WorkItem(29871, "https://github.com/dotnet/roslyn/issues/29871")] public void IdentityConversion_NullCoalescingOperator_05() { var source = @"#pragma warning disable 0649 struct A { public static implicit operator B(A a) => new B(); } class B { internal T F; } class C { static void F1(A? x1, B y1) { (x1 ?? y1)/*T:B!*/.F.ToString(); } static void F2(A? x2, B y2) { (x2 ?? y2)/*T:B!*/.F.ToString(); } static void F3(A x3, B? y3) { (y3 ?? x3)/*T:B!*/.F.ToString(); } static void F4(A x4, B? y4) { (y4 ?? x4)/*T:B!*/.F.ToString(); } static void F5(A? x5, B? y5) { (x5 ?? y5)/*T:B?*/.F.ToString(); (y5 ?? x5)/*T:B?*/.F.ToString(); } static void F6(A? x6, B? y6) { (x6 ?? y6)/*T:B?*/.F.ToString(); (y6 ?? x6)/*T:B?*/.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (8,16): warning CS8618: Non-nullable field 'F' is uninitialized. // internal T F; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(8, 16), // (14,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // (x1 ?? y1)/*T:B!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("A", "B").WithLocation(14, 10), // (14,9): warning CS8602: Dereference of a possibly null reference. // (x1 ?? y1)/*T:B!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x1 ?? y1)/*T:B!*/.F").WithLocation(14, 9), // (18,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // (x2 ?? y2)/*T:B!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("A", "B").WithLocation(18, 10), // (22,16): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // (y3 ?? x3)/*T:B!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("B", "B").WithLocation(22, 16), // (22,9): warning CS8602: Dereference of a possibly null reference. // (y3 ?? x3)/*T:B!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y3 ?? x3)/*T:B!*/.F").WithLocation(22, 9), // (26,16): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // (y4 ?? x4)/*T:B!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x4").WithArguments("B", "B").WithLocation(26, 16), // (30,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // (x5 ?? y5)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x5").WithArguments("A", "B").WithLocation(30, 10), // (30,10): warning CS8602: Dereference of a possibly null reference. // (x5 ?? y5)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x5 ?? y5").WithLocation(30, 10), // (30,9): warning CS8602: Dereference of a possibly null reference. // (x5 ?? y5)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(x5 ?? y5)/*T:B?*/.F").WithLocation(30, 9), // (31,16): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // (y5 ?? x5)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x5").WithArguments("B", "B").WithLocation(31, 16), // (31,10): warning CS8602: Dereference of a possibly null reference. // (y5 ?? x5)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y5 ?? x5").WithLocation(31, 10), // (31,9): warning CS8602: Dereference of a possibly null reference. // (y5 ?? x5)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(y5 ?? x5)/*T:B?*/.F").WithLocation(31, 9), // (35,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // (x6 ?? y6)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x6").WithArguments("A", "B").WithLocation(35, 10), // (35,10): warning CS8602: Dereference of a possibly null reference. // (x6 ?? y6)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x6 ?? y6").WithLocation(35, 10), // (36,16): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // (y6 ?? x6)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x6").WithArguments("B", "B").WithLocation(36, 16), // (36,10): warning CS8602: Dereference of a possibly null reference. // (y6 ?? x6)/*T:B?*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y6 ?? x6").WithLocation(36, 10)); } [Fact] public void IdentityConversion_NullCoalescingOperator_06() { var source = @"class C { static void F1(object? x, dynamic? y, dynamic z) { (x ?? y).ToString(); // 1 (x ?? z).ToString(); // ok (y ?? x).ToString(); // 2 (y ?? z).ToString(); // ok (z ?? x).ToString(); // 3 (z ?? y).ToString(); // 4 } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,10): warning CS8602: Dereference of a possibly null reference. // (x ?? y).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x ?? y").WithLocation(5, 10), // (7,10): warning CS8602: Dereference of a possibly null reference. // (y ?? x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(7, 10), // (9,10): warning CS8602: Dereference of a possibly null reference. // (z ?? x).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z ?? x").WithLocation(9, 10), // (10,10): warning CS8602: Dereference of a possibly null reference. // (z ?? y).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z ?? y").WithLocation(10, 10)); } [Fact] public void ImplicitConversion_NullCoalescingOperator_01() { var source0 = @"public class UnknownNull { public object Object; public string String; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source1 = @"public class MaybeNull { public object? Object; public string? String; } public class NotNull { public object Object = new object(); public string String = string.Empty; }"; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics(); var ref1 = comp1.EmitToImageReference(); var source = @"class C { static void F1(bool b, UnknownNull x1, UnknownNull y1) { if (b) { (x1.Object ?? y1.String)/*T:object!*/.ToString(); } else { (y1.String ?? x1.Object)/*T:object!*/.ToString(); } } static void F2(bool b, UnknownNull x2, MaybeNull y2) { if (b) { (x2.Object ?? y2.String)/*T:object?*/.ToString(); // 1 } else { (y2.String ?? x2.Object)/*T:object!*/.ToString(); } } static void F3(bool b, MaybeNull x3, UnknownNull y3) { if (b) { (x3.Object ?? y3.String)/*T:object!*/.ToString(); } else { (y3.String ?? x3.Object)/*T:object?*/.ToString(); // 2 } } static void F4(bool b, MaybeNull x4, MaybeNull y4) { if (b) { (x4.Object ?? y4.String)/*T:object?*/.ToString(); // 3 } else { (y4.String ?? x4.Object)/*T:object?*/.ToString(); // 4 } } static void F5(bool b, UnknownNull x5, NotNull y5) { if (b) { (x5.Object ?? y5.String)/*T:object!*/.ToString(); } else { (y5.String ?? x5.Object)/*T:object!*/.ToString(); } } static void F6(bool b, NotNull x6, UnknownNull y6) { if (b) { (x6.Object ?? y6.String)/*T:object!*/.ToString(); } else { (y6.String ?? x6.Object)/*T:object!*/.ToString(); } } static void F7(bool b, MaybeNull x7, NotNull y7) { if (b) { (x7.Object ?? y7.String)/*T:object!*/.ToString(); } else { (y7.String ?? x7.Object)/*T:object?*/.ToString(); // 5 } } static void F8(bool b, NotNull x8, MaybeNull y8) { if (b) { (x8.Object ?? y8.String)/*T:object?*/.ToString(); // 6 } else { (y8.String ?? x8.Object)/*T:object!*/.ToString(); } } static void F9(bool b, NotNull x9, NotNull y9) { if (b) { (x9.Object ?? y9.String)/*T:object!*/.ToString(); } else { (y9.String ?? x9.Object)/*T:object!*/.ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0, ref1 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (14,14): warning CS8602: Dereference of a possibly null reference. // (x2.Object ?? y2.String)/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2.Object ?? y2.String").WithLocation(14, 14), // (24,14): warning CS8602: Dereference of a possibly null reference. // (y3.String ?? x3.Object)/*T:object?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y3.String ?? x3.Object").WithLocation(24, 14), // (30,14): warning CS8602: Dereference of a possibly null reference. // (x4.Object ?? y4.String)/*T:object?*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4.Object ?? y4.String").WithLocation(30, 14), // (32,14): warning CS8602: Dereference of a possibly null reference. // (y4.String ?? x4.Object)/*T:object?*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y4.String ?? x4.Object").WithLocation(32, 14), // (56,14): warning CS8602: Dereference of a possibly null reference. // (y7.String ?? x7.Object)/*T:object?*/.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y7.String ?? x7.Object").WithLocation(56, 14), // (62,14): warning CS8602: Dereference of a possibly null reference. // (x8.Object ?? y8.String)/*T:object?*/.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x8.Object ?? y8.String").WithLocation(62, 14)); } [Fact] public void ImplicitConversion_NullCoalescingOperator_02() { var source = @"#pragma warning disable 0649 class A { internal T F; } class B : A { } class C { static void F(A? x, B y) { (x ?? y).F.ToString(); // 1 (y ?? x).F.ToString(); // 2 } static void G(A z, B? w) { (z ?? w).F.ToString(); // 3 (w ?? z).F.ToString(); // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,16): warning CS8618: Non-nullable field 'F' is uninitialized. // internal T F; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(4, 16), // (11,15): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (x ?? y).F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("B", "A").WithLocation(11, 15), // (12,10): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (y ?? x).F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("B", "A").WithLocation(12, 10), // (12,10): warning CS8602: Dereference of a possibly null reference. // (y ?? x).F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(12, 10), // (16,15): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (z ?? w).F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("B", "A").WithLocation(16, 15), // (16,10): warning CS8602: Dereference of a possibly null reference. // (z ?? w).F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z ?? w").WithLocation(16, 10), // (16,9): warning CS8602: Dereference of a possibly null reference. // (z ?? w).F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(z ?? w).F").WithLocation(16, 9), // (17,10): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // (w ?? z).F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("B", "A").WithLocation(17, 10), // (17,10): warning CS8602: Dereference of a possibly null reference. // (w ?? z).F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w ?? z").WithLocation(17, 10), // (17,9): warning CS8602: Dereference of a possibly null reference. // (w ?? z).F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(w ?? z).F").WithLocation(17, 9)); } [Fact] public void ImplicitConversion_NullCoalescingOperator_03() { var source = @"interface IIn { void F(T x, T y); } class C { static void F(bool b, IIn? x, IIn y) { if (b) { (x ?? y)/*T:IIn!*/.F(string.Empty, null); // 1 } else { (y ?? x)/*T:IIn?*/.F(string.Empty, null); // 2 } } static void G(bool b, IIn z, IIn? w) { if (b) { (z ?? w)/*T:IIn?*/.F(string.Empty, null); // 3 } else { (w ?? z)/*T:IIn!*/.F(string.Empty, null); // 4 } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,14): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // (x ?? y)/*T:IIn!*/.F(string.Empty, null); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(10, 14), // (12,14): warning CS8602: Dereference of a possibly null reference. // (y ?? x)/*T:IIn?*/.F(string.Empty, null); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(12, 14), // (12,19): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // (y ?? x)/*T:IIn?*/.F(string.Empty, null); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(12, 19), // (18,14): warning CS8602: Dereference of a possibly null reference. // (z ?? w)/*T:IIn?*/.F(string.Empty, null); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z ?? w").WithLocation(18, 14), // (18,57): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // (z ?? w)/*T:IIn?*/.F(string.Empty, null); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(18, 57), // (20,57): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // (w ?? z)/*T:IIn!*/.F(string.Empty, null); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(20, 57)); } [Fact] public void ImplicitConversion_NullCoalescingOperator_04() { var source = @"interface IOut { T P { get; } } class C { static void F(bool b, IOut? x, IOut y) { if (b) { (x ?? y)/*T:IOut!*/.P.ToString(); // 1 } else { (y ?? x)/*T:IOut?*/.P.ToString(); // 2 } } static void G(bool b, IOut z, IOut? w) { if (b) { (z ?? w)/*T:IOut?*/.P.ToString(); // 3 } else { (w ?? z)/*T:IOut!*/.P.ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,19): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // (x ?? y)/*T:IOut!*/.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(10, 19), // (12,14): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // (y ?? x)/*T:IOut?*/.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(12, 14), // (12,14): warning CS8602: Dereference of a possibly null reference. // (y ?? x)/*T:IOut?*/.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y ?? x").WithLocation(12, 14), // (18,13): warning CS8602: Dereference of a possibly null reference. // (z ?? w)/*T:IOut?*/.P.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(z ?? w)/*T:IOut?*/.P").WithLocation(18, 13), // (18,14): warning CS8602: Dereference of a possibly null reference. // (z ?? w)/*T:IOut?*/.P.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z ?? w").WithLocation(18, 14), // (20,13): warning CS8602: Dereference of a possibly null reference. // (w ?? z)/*T:IOut!*/.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(w ?? z)/*T:IOut!*/.P").WithLocation(20, 13)); } [Fact] public void Loop_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1? x1, CL1 y1, CL1? z1) { x1 = y1; x1.M1(); // 1 for (int i = 0; i < 2; i++) { x1.M1(); // 2 x1 = z1; } } CL1 Test2(CL1? x2, CL1 y2, CL1? z2) { x2 = y2; x2.M1(); // 1 for (int i = 0; i < 2; i++) { x2 = z2; x2.M1(); // 2 y2 = z2; y2.M2(y2); if (i == 1) { return x2; } } return y2; } } class CL1 { public void M1() { } public void M2(CL1 x) { } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,13): warning CS8602: Dereference of a possibly null reference. // x1.M1(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(15, 13), // (28,13): warning CS8602: Dereference of a possibly null reference. // x2.M1(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(28, 13), // (29,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = z2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z2").WithLocation(29, 18), // (30,13): warning CS8602: Dereference of a possibly null reference. // y2.M2(y2); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(30, 13)); } [Fact] public void Loop_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1? x1, CL1 y1, CL1? z1) { x1 = y1; if (x1 == null) {} // 1 for (int i = 0; i < 2; i++) { if (x1 == null) {} // 2 x1 = z1; } } void Test2(CL1? x2, CL1 y2, CL1? z2) { x2 = y2; if (x2 == null) {} // 1 for (int i = 0; i < 2; i++) { x2 = z2; if (x2 == null) {} // 2 } } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Loop_03() { var source0 = @"public class A { public object F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var source1 = @"#pragma warning disable 8618 class B { object G; static object F1(B b1, object? o) { for (int i = 0; i < 2; i++) { b1.G = o; } return b1.G; } static object F2(B b2, A a) { for (int i = 0; i < 2; i++) { b2.G = a.F; } return b2.G; } static object F3(B b3, object? o, A a) { for (int i = 0; i < 2; i++) { if (i % 2 == 0) b3.G = o; else b3.G = a.F; } return b3.G; } }"; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { comp0.EmitToImageReference() }); comp1.VerifyDiagnostics( // (9,20): warning CS8601: Possible null reference assignment. // b1.G = o; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "o").WithLocation(9, 20), // (11,16): warning CS8603: Possible null reference return. // return b1.G; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "b1.G").WithLocation(11, 16), // (26,24): warning CS8601: Possible null reference assignment. // b3.G = o; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "o").WithLocation(26, 24), // (30,16): warning CS8603: Possible null reference return. // return b3.G; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "b3.G").WithLocation(30, 16)); } [Fact] public void Loop_04() { var source0 = @"public class A { public object F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var source1 = @"#pragma warning disable 8618 class C { static object F1(A a1, object? o) { for (int i = 0; i < 2; i++) { a1.F = o; } return a1.F; } static object F2(A a2, object o) { for (int i = 0; i < 2; i++) { a2.F = o; } return a2.F; } static object F3(A a3, object? o, A a) { for (int i = 0; i < 2; i++) { if (i % 2 == 0) a3.F = o; else a3.F = a.F; } return a3.F; } }"; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { comp0.EmitToImageReference() }); comp1.VerifyDiagnostics( // (10,16): warning CS8603: Possible null reference return. // return a1.F; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "a1.F").WithLocation(10, 16), // (29,16): warning CS8603: Possible null reference return. // return a3.F; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "a3.F").WithLocation(29, 16)); } [Fact] public void Var_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? Test1() { var x1 = (CL1)null; return x1; } CL1? Test2(CL1 x2) { var y2 = x2; y2 = null; return y2; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // var x1 = (CL1)null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(CL1)null").WithLocation(10, 18), // (17,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(17, 14)); } [Fact] public void Var_NonNull() { var source = @"class C { static void F(string str) { var s = str; s.ToString(); s = null; s.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 13), // (8,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 9)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_NonNull_CSharp7() { var source = @"class C { static void Main() { var s = string.Empty; s.ToString(); s = null; s.ToString(); } }"; var comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_01() { var source = @"class C { static void F(string? s) { var t = s; t.ToString(); t = null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(6, 9)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_02() { var source = @"class C { static void F(string? s) { t = null/*T:?*/; var t = s; t.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS0841: Cannot use local variable 't' before it is declared // t = null; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "t").WithArguments("t").WithLocation(5, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(7, 9)); comp.VerifyTypes(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_03() { var source = @"class C { static void F(string? s) { if (s == null) { return; } var t = s; t.ToString(); t = null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // t = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 13)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/29856: Type should be `string!`. Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); // https://github.com/dotnet/roslyn/issues/29856: IsNullable should be inferred nullable state: false. Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_04() { var source = @"class C { static void F(int n) { string? s = string.Empty; while (n-- > 0) { var t = s; t.ToString(); t = null; s = null; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(9, 13)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); Assert.Equal("System.String?", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Annotated, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_05() { var source = @"class C { static void F(int n, string? s) { while (n-- > 0) { var t = s; t.ToString(); t = null; s = string.Empty; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 13)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_06() { var source = @"class C { static void F(int n) { string? s = string.Empty; while (n-- > 0) { var t = s; t.ToString(); t = null; if (n % 2 == 0) s = null; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(9, 13)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().Skip(1).First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_07() { var source = @"class C { static void F(int n) { string? s = string.Empty; while (n-- > 0) { var t = s; t.ToString(); t = null; if (n % 2 == 0) s = string.Empty; else s = null; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(9, 13)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().Skip(1).First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_FlowAnalysis_08() { var source = @"class C { static void F(string? s) { var t = s!; t/*T:string!*/.ToString(); t = null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // t = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 13)); comp.VerifyTypes(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); // Need to verify the semantic model // Tracked by https://github.com/dotnet/roslyn/issues/32661 var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Var_Cycle() { var source = @"class C { static void Main() { var s = s; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (5,17): error CS0841: Cannot use local variable 's' before it is declared // var s = s; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "s").WithArguments("s").WithLocation(5, 17)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); var type = symbol.TypeWithAnnotations; Assert.True(type.Type.IsErrorType()); Assert.Equal("var", type.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, type.NullableAnnotation); } [Fact] public void Var_ConditionalOperator() { var source = @"class C { static void F(bool b, string s) { var s0 = b ? s : s; var s1 = b ? s : null; var s2 = b ? null : s; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); // https://github.com/dotnet/roslyn/issues/29856: Inferred nullability: false symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); // https://github.com/dotnet/roslyn/issues/29856: Inferred nullability: true symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[2]); Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString()); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); // https://github.com/dotnet/roslyn/issues/29856: Inferred nullability: true } [Fact] public void Var_Array_01() { var source = @"class C { static void F(string str) { var s = new[] { str }; s[0].ToString(); var t = new[] { str, null }; t[0].ToString(); var u = new[] { 1, null }; u[0].ToString(); var v = new[] { null, (int?)2 }; v[0].ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,28): error CS0037: Cannot convert null to 'int' because it is a non-nullable value type // var u = new[] { 1, null }; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(9, 28), // (8,9): warning CS8602: Dereference of a possibly null reference. // t[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t[0]").WithLocation(8, 9)); } [Fact] public void Var_Array_02() { var source = @"delegate void D(); class C { static void Main() { var a = new[] { new D(Main), () => { } }; a[0].ToString(); var b = new[] { new D(Main), null }; b[0].ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // b[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(9, 9)); } [Fact] public void Array_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1? [] x1) { CL1? y1 = x1[0]; CL1 z1 = x1[0]; } void Test2(CL1 [] x2, CL1 y2, CL1? z2) { x2[0] = y2; x2[1] = z2; } void Test3(CL1 [] x3) { CL1? y3 = x3[0]; CL1 z3 = x3[0]; } void Test4(CL1? [] x4, CL1 y4, CL1? z4) { x4[0] = y4; x4[1] = z4; } void Test5(CL1 y5, CL1? z5) { var x5 = new CL1 [] { y5, z5 }; } void Test6(CL1 y6, CL1? z6) { var x6 = new CL1 [,] { {y6}, {z6} }; } void Test7(CL1 y7, CL1? z7) { var u7 = new CL1? [] { y7, z7 }; var v7 = new CL1? [,] { {y7}, {z7} }; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z1 = x1[0]; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1[0]").WithLocation(11, 18), // (17,17): warning CS8601: Possible null reference assignment. // x2[1] = z2; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z2").WithLocation(17, 17), // (34,35): warning CS8601: Possible null reference assignment. // var x5 = new CL1 [] { y5, z5 }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z5").WithLocation(34, 35), // (39,39): warning CS8601: Possible null reference assignment. // var x6 = new CL1 [,] { {y6}, {z6} }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z6").WithLocation(39, 39) ); } [Fact] public void Array_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 y1, CL1? z1) { CL1? [] u1 = new [] { y1, z1 }; CL1? [,] v1 = new [,] { {y1}, {z1} }; } void Test2(CL1 y2, CL1? z2) { var u2 = new [] { y2, z2 }; var v2 = new [,] { {y2}, {z2} }; u2[0] = z2; v2[0,0] = z2; } void Test3(CL1 y3, CL1? z3) { CL1? [] u3; CL1? [,] v3; u3 = new [] { y3, z3 }; v3 = new [,] { {y3}, {z3} }; } void Test4(CL1 y4, CL1? z4) { var u4 = new [] { y4 }; var v4 = new [,] {{y4}}; u4[0] = z4; v4[0,0] = z4; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (37,17): warning CS8601: Possible null reference assignment. // u4[0] = z4; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z4").WithLocation(37, 17), // (38,19): warning CS8601: Possible null reference assignment. // v4[0,0] = z4; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z4").WithLocation(38, 19) ); } [Fact] public void Array_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1() { int[]? u1 = new [] { 1, 2 }; u1 = null; var z1 = u1[0]; } void Test2() { int[]? u1 = new [] { 1, 2 }; u1 = null; var z1 = u1?[u1[0]]; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,18): warning CS8602: Dereference of a possibly null reference. // var z1 = u1[0]; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u1").WithLocation(12, 18) ); } [Fact] public void Array_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL1 y1, CL1? z1) { CL1 [] u1; CL1 [,] v1; u1 = new [] { y1, z1 }; v1 = new [,] { {y1}, {z1} }; } void Test3(CL1 y2, CL1? z2) { CL1 [] u2; CL1 [,] v2; var a2 = new [] { y2, z2 }; var b2 = new [,] { {y2}, {z2} }; u2 = a2; v2 = b2; } void Test8(CL1 y8, CL1? z8) { CL1 [] x8 = new [] { y8, z8 }; } void Test9(CL1 y9, CL1? z9) { CL1 [,] x9 = new [,] { {y9}, {z9} }; } void Test11(CL1 y11, CL1? z11) { CL1? [] u11; CL1? [,] v11; u11 = new [] { y11, z11 }; v11 = new [,] { {y11}, {z11} }; } void Test13(CL1 y12, CL1? z12) { CL1? [] u12; CL1? [,] v12; var a12 = new [] { y12, z12 }; var b12 = new [,] { {y12}, {z12} }; u12 = a12; v12 = b12; } void Test18(CL1 y18, CL1? z18) { CL1? [] x18 = new [] { y18, z18 }; } void Test19(CL1 y19, CL1? z19) { CL1? [,] x19 = new [,] { {y19}, {z19} }; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,14): warning CS8619: Nullability of reference types in value of type 'CL1?[]' doesn't match target type 'CL1[]'. // u1 = new [] { y1, z1 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new [] { y1, z1 }").WithArguments("CL1?[]", "CL1[]").WithLocation(13, 14), // (14,14): warning CS8619: Nullability of reference types in value of type 'CL1?[*,*]' doesn't match target type 'CL1[*,*]'. // v1 = new [,] { {y1}, {z1} }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new [,] { {y1}, {z1} }").WithArguments("CL1?[*,*]", "CL1[*,*]").WithLocation(14, 14), // (25,14): warning CS8619: Nullability of reference types in value of type 'CL1?[]' doesn't match target type 'CL1[]'. // u2 = a2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("CL1?[]", "CL1[]").WithLocation(25, 14), // (26,14): warning CS8619: Nullability of reference types in value of type 'CL1?[*,*]' doesn't match target type 'CL1[*,*]'. // v2 = b2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b2").WithArguments("CL1?[*,*]", "CL1[*,*]").WithLocation(26, 14), // (31,21): warning CS8619: Nullability of reference types in value of type 'CL1?[]' doesn't match target type 'CL1[]'. // CL1 [] x8 = new [] { y8, z8 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new [] { y8, z8 }").WithArguments("CL1?[]", "CL1[]").WithLocation(31, 21), // (36,22): warning CS8619: Nullability of reference types in value of type 'CL1?[*,*]' doesn't match target type 'CL1[*,*]'. // CL1 [,] x9 = new [,] { {y9}, {z9} }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new [,] { {y9}, {z9} }").WithArguments("CL1?[*,*]", "CL1[*,*]").WithLocation(36, 22) ); } [Fact] public void Array_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1() { int[]? u1 = new [] { 1, 2 }; var z1 = u1.Length; } void Test2() { int[]? u2 = new [] { 1, 2 }; u2 = null; var z2 = u2.Length; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (18,18): warning CS8602: Dereference of a possibly null reference. // var z2 = u2.Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2").WithLocation(18, 18) ); } [Fact] public void Array_06() { const string source = @" class C { static void Main() { } object Test1() { object []? u1 = null; return u1; } object Test2() { object [][]? u2 = null; return u2; } object Test3() { object []?[]? u3 = null; return u3; } } "; var expected = new[] { // (10,18): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // object []? u1 = null; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(10, 18), // (15,20): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // object [][]? u2 = null; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(15, 20), // (20,18): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // object []?[]? u3 = null; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(20, 18), // (20,21): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // object []?[]? u3 = null; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(20, 21) }; var c = CreateCompilation(source, parseOptions: TestOptions.Regular7); c.VerifyDiagnostics(expected); c = CreateCompilation(source, parseOptions: TestOptions.RegularDefault); c.VerifyDiagnostics(expected); } [Fact] public void Array_07() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1() { object? [] u1 = new [] { null, new object() }; u1 = null; } void Test2() { object [] u2 = new [] { null, new object() }; } void Test3() { var u3 = new object [] { null, new object() }; } object? Test4() { object []? u4 = null; return u4; } object Test5() { object? [] u5 = null; return u5; } void Test6() { object [][,]? u6 = null; u6[0] = null; u6[0][0,0] = null; u6[0][0,0].ToString(); } void Test7() { object [][,] u7 = null; u7[0] = null; u7[0][0,0] = null; } void Test8() { object []?[,] u8 = null; u8[0,0] = null; u8[0,0].ToString(); u8[0,0][0] = null; u8[0,0][0].ToString(); } void Test9() { object []?[,]? u9 = null; u9[0,0] = null; u9[0,0][0] = null; u9[0,0][0].ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // u1 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 14), // (16,24): warning CS8619: Nullability of reference types in value of type 'object?[]' doesn't match target type 'object[]'. // object [] u2 = new [] { null, new object() }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new [] { null, new object() }").WithArguments("object?[]", "object[]").WithLocation(16, 24), // (21,34): warning CS8625: Cannot convert null literal to non-nullable reference type. // var u3 = new object [] { null, new object() }; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(21, 34), // (32,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // object? [] u5 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(32, 25), // (33,16): warning CS8603: Possible null reference return. // return u5; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "u5").WithLocation(33, 16), // (39,9): warning CS8602: Dereference of a possibly null reference. // u6[0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6").WithLocation(39, 9), // (39,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // u6[0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(39, 17), // (40,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u6[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(40, 22), // (46,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // object [][,] u7 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(46, 27), // (47,9): warning CS8602: Dereference of a possibly null reference. // u7[0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u7").WithLocation(47, 9), // (47,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // u7[0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(47, 17), // (48,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u7[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 22), // (53,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // object []?[,] u8 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(53, 28), // (54,9): warning CS8602: Dereference of a possibly null reference. // u8[0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8").WithLocation(54, 9), // (55,9): warning CS8602: Dereference of a possibly null reference. // u8[0,0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8[0,0]").WithLocation(55, 9), // (56,9): warning CS8602: Dereference of a possibly null reference. // u8[0,0][0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8[0,0]").WithLocation(56, 9), // (56,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u8[0,0][0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(56, 22), // (57,9): warning CS8602: Dereference of a possibly null reference. // u8[0,0][0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u8[0,0]").WithLocation(57, 9), // (63,9): warning CS8602: Dereference of a possibly null reference. // u9[0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9").WithLocation(63, 9), // (64,9): warning CS8602: Dereference of a possibly null reference. // u9[0,0][0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0,0]").WithLocation(64, 9), // (64,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u9[0,0][0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(64, 22), // (65,9): warning CS8602: Dereference of a possibly null reference. // u9[0,0][0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0,0]").WithLocation(65, 9) ); } [Fact] public void Array_08() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test3() { var u3 = new object? [] { null }; } void Test6() { var u6 = new object [,]?[] {null, new object[,] {{null}}}; u6[0] = null; u6[0][0,0] = null; u6[0][0,0].ToString(); } void Test7() { var u7 = new object [][,] {null, new object[,] {{null}}}; u7[0] = null; u7[0][0,0] = null; } void Test8() { object [][,]? u8 = new object [][,] {null, new object[,] {{null}}}; u8[0] = null; u8[0][0,0] = null; u8[0][0,0].ToString(); } void Test9() { object [,]?[]? u9 = new object [,]?[] {null, new object[,] {{null}}}; u9[0] = null; u9[0][0,0] = null; u9[0][0,0].ToString(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (16,53): warning CS8625: Cannot convert null literal to non-nullable reference type. // new object[,] {{null}}}; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 53), // (18,9): warning CS8602: Dereference of a possibly null reference. // u6[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6[0]").WithLocation(18, 9), // (18,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u6[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(18, 22), // (19,9): warning CS8602: Dereference of a possibly null reference. // u6[0][0,0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u6[0]").WithLocation(19, 9), // (24,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // var u7 = new object [][,] {null, Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(24, 36), // (25,52): warning CS8625: Cannot convert null literal to non-nullable reference type. // new object[,] {{null}}}; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(25, 52), // (26,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // u7[0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(26, 17), // (27,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u7[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(27, 22), // (32,46): warning CS8625: Cannot convert null literal to non-nullable reference type. // object [][,]? u8 = new object [][,] {null, Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(32, 46), // (33,53): warning CS8625: Cannot convert null literal to non-nullable reference type. // new object[,] {{null}}}; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(33, 53), // (34,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // u8[0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(34, 17), // (35,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u8[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(35, 22), // (42,54): warning CS8625: Cannot convert null literal to non-nullable reference type. // new object[,] {{null}}}; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(42, 54), // (44,9): warning CS8602: Dereference of a possibly null reference. // u9[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0]").WithLocation(44, 9), // (44,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // u9[0][0,0] = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(44, 22), // (45,9): warning CS8602: Dereference of a possibly null reference. // u9[0][0,0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u9[0]").WithLocation(45, 9) ); } [Fact] public void Array_09() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1, CL0 y1) { var u1 = new [] { x1, y1 }; var a1 = new [] { y1, x1 }; var v1 = new CL0[] { x1, y1 }; var w1 = new CL0[] { x1, y1 }; } } class CL0 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,27): warning CS8619: Nullability of reference types in value of type 'CL0' doesn't match target type 'CL0'. // var u1 = new [] { x1, y1 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("CL0", "CL0").WithLocation(10, 27), // (11,31): warning CS8619: Nullability of reference types in value of type 'CL0' doesn't match target type 'CL0'. // var a1 = new [] { y1, x1 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("CL0", "CL0").WithLocation(11, 31), // (12,43): warning CS8619: Nullability of reference types in value of type 'CL0' doesn't match target type 'CL0'. // var v1 = new CL0[] { x1, y1 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("CL0", "CL0").WithLocation(12, 43), // (13,38): warning CS8619: Nullability of reference types in value of type 'CL0' doesn't match target type 'CL0'. // var w1 = new CL0[] { x1, y1 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("CL0", "CL0").WithLocation(13, 38) ); } [Fact] public void Array_10() { var source = @"class C { static void F1() { T[] a1; a1 = new T[] { default }; // 1 a1 = new T[] { default(T) }; // 2 } static void F2() where T : class { T[] a2; a2 = new T[] { null }; // 3 a2 = new T[] { default }; // 4 a2 = new T[] { default(T) }; // 5 } static void F3() where T : struct { T[] a3; a3 = new T[] { default }; a3 = new T[] { default(T) }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,24): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // a1 = new T[] { default }; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 24), // (7,24): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // a1 = new T[] { default(T) }; // 2 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(7, 24), // (12,24): warning CS8625: Cannot convert null literal to non-nullable reference type. // a2 = new T[] { null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 24), // (13,24): warning CS8625: Cannot convert null literal to non-nullable reference type. // a2 = new T[] { default }; // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(13, 24), // (14,24): warning CS8625: Cannot convert null literal to non-nullable reference type. // a2 = new T[] { default(T) }; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(T)").WithLocation(14, 24) ); } [Fact] public void ImplicitlyTypedArrayCreation_01() { var source = @"class C { static void F(object x, object? y) { var a = new[] { x, x }; a.ToString(); a[0].ToString(); var b = new[] { x, y }; b.ToString(); b[0].ToString(); var c = new[] { b }; c[0].ToString(); c[0][0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // b[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(10, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // c[0][0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0][0]").WithLocation(13, 9)); } [Fact] [WorkItem(33346, "https://github.com/dotnet/roslyn/issues/33346")] [WorkItem(30376, "https://github.com/dotnet/roslyn/issues/30376")] public void ImplicitlyTypedArrayCreation_02() { var source = @"class C { static void F(object x, object? y) { var a = new[] { x }; a[0].ToString(); var b = new[] { y }; b[0].ToString(); // 1 } static void F(object[] a, object?[] b) { var c = new[] { a, b }; c[0][0].ToString(); // 2 var d = new[] { a, b! }; d[0][0].ToString(); // 3 var e = new[] { b!, a }; e[0][0].ToString(); // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // b[0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(8, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // c[0][0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0][0]").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // d[0][0].ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0][0]").WithLocation(15, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // e[0][0].ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e[0][0]").WithLocation(17, 9) ); } [Fact, WorkItem(30376, "https://github.com/dotnet/roslyn/issues/30376")] public void ImplicitlyTypedArrayCreation_02_TopLevelNullability() { var source = @"class C { static void F(object? y) { var b = new[] { y! }; b[0].ToString(); } static void F(object[]? a, object?[]? b) { var c = new[] { a, b }; _ = c[0].Length; var d = new[] { a, b! }; _ = d[0].Length; var e = new[] { b!, a }; _ = e[0].Length; var f = new[] { b!, a! }; _ = f[0].Length; var g = new[] { a!, b! }; _ = g[0].Length; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8602: Dereference of a possibly null reference. // _ = c[0].Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0]").WithLocation(11, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // _ = d[0].Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0]").WithLocation(13, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // _ = e[0].Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e[0]").WithLocation(15, 13)); } [Fact] public void ImplicitlyTypedArrayCreation_03() { var source = @"class C { static void F(object x, object? y) { (new[] { x, x })[1].ToString(); (new[] { y, x })[1].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, x })[1].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, x })[1]").WithLocation(6, 9)); } [Fact] public void ImplicitlyTypedArrayCreation_04() { var source = @"class C { static void F() { object? o = new object(); var a = new[] { o }; a[0].ToString(); var b = new[] { a }; b[0][0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ImplicitlyTypedArrayCreation_05() { var source = @"class C { static void F(int n) { object? o = new object(); while (n-- > 0) { var a = new[] { o }; a[0].ToString(); var b = new[] { a }; b[0][0].ToString(); o = null; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // a[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a[0]").WithLocation(9, 13), // (11,13): warning CS8602: Dereference of a possibly null reference. // b[0][0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0][0]").WithLocation(11, 13)); } [Fact] public void ImplicitlyTypedArrayCreation_06() { var source = @"class C { static void F(string s) { var a = new[] { new object(), (string)null }; a[0].ToString(); var b = new[] { (object)null, s }; b[0].ToString(); var c = new[] { s, (object)null }; c[0].ToString(); var d = new[] { (string)null, new object() }; d[0].ToString(); var e = new[] { new object(), (string)null! }; e[0].ToString(); var f = new[] { (object)null!, s }; f[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,39): warning CS8600: Converting null literal or possible null value to non-nullable type. // var a = new[] { new object(), (string)null }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(5, 39), // (6,9): warning CS8602: Dereference of a possibly null reference. // a[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a[0]").WithLocation(6, 9), // (7,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // var b = new[] { (object)null, s }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)null").WithLocation(7, 25), // (8,9): warning CS8602: Dereference of a possibly null reference. // b[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(8, 9), // (9,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // var c = new[] { s, (object)null }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)null").WithLocation(9, 28), // (10,9): warning CS8602: Dereference of a possibly null reference. // c[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0]").WithLocation(10, 9), // (11,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // var d = new[] { (string)null, new object() }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(11, 25), // (12,9): warning CS8602: Dereference of a possibly null reference. // d[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0]").WithLocation(12, 9)); } [Fact] public void ImplicitlyTypedArrayCreation_NestedNullability_Derived() { var source0 = @"public class A { public static B F; } public class B { } public class C0 : B { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C1 : B { } class C2 : B { } class Program { static void F(B x, B y, C0 cz, C1 cx, C2 cy) { var z = A.F/*T:B!*/; object o; o = (new[] { x, cx })[0]/*B*/; o = (new[] { x, cy })[0]/*B*/; // 1 o = (new[] { x, cz })[0]/*B*/; o = (new[] { y, cx })[0]/*B*/; // 2 o = (new[] { cy, y })[0]/*B*/; o = (new[] { cz, y })[0]/*B*/; o = (new[] { cx, z })[0]/*B*/; o = (new[] { cy, z })[0]/*B*/; o = (new[] { cz, z })[0]/*B*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,25): warning CS8619: Nullability of reference types in value of type 'C2' doesn't match target type 'B'. // o = (new[] { x, cy })[0]/*B*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "cy").WithArguments("C2", "B").WithLocation(10, 25), // (12,25): warning CS8619: Nullability of reference types in value of type 'C1' doesn't match target type 'B'. // o = (new[] { y, cx })[0]/*B*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "cx").WithArguments("C1", "B").WithLocation(12, 25) ); comp.VerifyTypes(); } [Fact] [WorkItem(29888, "https://github.com/dotnet/roslyn/issues/29888")] public void ImplicitlyTypedArrayCreation_08() { var source = @"class C { } class C { static void F(C? a, C b) { if (a == null) { var c = new[] { a, b }; c[0].ToString(); var d = new[] { b, a }; d[0].ToString(); } else { var c = new[] { a, b }; c[0].ToString(); var d = new[] { b, a }; d[0].ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,32): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var c = new[] { a, b }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(8, 32), // (9,13): warning CS8602: Dereference of a possibly null reference. // c[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0]").WithLocation(9, 13), // (10,29): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var d = new[] { b, a }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(10, 29), // (11,13): warning CS8602: Dereference of a possibly null reference. // d[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0]").WithLocation(11, 13), // (15,32): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var c = new[] { a, b }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(15, 32), // (17,29): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var d = new[] { b, a }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("C", "C").WithLocation(17, 29) ); } [Fact] public void ImplicitlyTypedArrayCreation_09() { var source = @"class C { static void F(C x1, Unknown? y1) { var a1 = new[] { x1, y1 }; a1[0].ToString(); var b1 = new[] { y1, x1 }; b1[0].ToString(); } static void G(C? x2, Unknown y2) { var a2 = new[] { x2, y2 }; a2[0].ToString(); var b2 = new[] { y2, x2 }; b2[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,26): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void G(C? x2, Unknown y2) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(10, 26), // (3,25): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?) // static void F(C x1, Unknown? y1) Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(3, 25), // (5,18): error CS0826: No best type found for implicitly-typed array // var a1 = new[] { x1, y1 }; Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "new[] { x1, y1 }").WithLocation(5, 18), // (7,18): error CS0826: No best type found for implicitly-typed array // var b1 = new[] { y1, x1 }; Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "new[] { y1, x1 }").WithLocation(7, 18)); } [Fact] public void ImplicitlyTypedArrayCreation_TopLevelNullability_01() { var source0 = @"public class A { public static object F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F(object? x, object y) { var z = A.F/*T:object!*/; object? o; o = (new[] { x, x })[0]/*T:object?*/; o = (new[] { x, y })[0]/*T:object?*/; o = (new[] { x, z })[0]/*T:object?*/; o = (new[] { y, x })[0]/*T:object?*/; o = (new[] { y, y })[0]/*T:object!*/; o = (new[] { y, z })[0]/*T:object!*/; o = (new[] { z, x })[0]/*T:object?*/; o = (new[] { z, y })[0]/*T:object!*/; o = (new[] { z, z })[0]/*T:object!*/; o = (new[] { x, y, z })[0]/*T:object?*/; o = (new[] { z, y, x })[0]/*T:object?*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void ImplicitlyTypedArrayCreation_TopLevelNullability_02() { var source = @"class C { static void F(T t, U u) where T : class? where U : class, T { object? o; o = (new[] { t, t })[0]/*T:T*/; o = (new[] { t, u })[0]/*T:T*/; o = (new[] { u, t })[0]/*T:T*/; o = (new[] { u, u })[0]/*T:U!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] [Fact] public void ImplicitlyTypedArrayCreation_NestedNullability_Invariant() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class Program { static void F(bool b, B x, B y) { var z = A.F/*T:B!*/; object o; o = (new[] { x, y })[0]/*T:B!*/; // 1 o = (new[] { x, z })[0]/*T:B!*/; o = (new[] { y, x })[0]/*T:B!*/; // 2 o = (new[] { y, z })[0]/*T:B!*/; o = (new[] { z, x })[0]/*T:B!*/; o = (new[] { z, y })[0]/*T:B!*/; o = (new[] { x, y, z })[0]/*T:B!*/; // 3 o = (new[] { z, y, x })[0]/*T:B!*/; // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (7,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (new[] { x, y })[0]/*T:B!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(7, 22), // (9,25): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (new[] { y, x })[0]/*T:B!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 25), // (13,22): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (new[] { x, y, z })[0]/*T:B!*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(13, 22), // (14,28): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // o = (new[] { z, y, x })[0]/*T:B!*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(14, 28) ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_01() { var source0 = @"public class A { public static I F; public static IIn FIn; public static IOut FOut; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F(I x, I y) { var z = A.F/*T:I!*/; object o; o = (new[] { x, x })[0]/*T:I!*/; o = (new[] { x, y })[0]/*T:I!*/; // 1 o = (new[] { x, z })[0]/*T:I!*/; o = (new[] { y, x })[0]/*T:I!*/; // 2 o = (new[] { y, y })[0]/*T:I!*/; o = (new[] { y, z })[0]/*T:I!*/; o = (new[] { z, x })[0]/*T:I!*/; o = (new[] { z, y })[0]/*T:I!*/; o = (new[] { z, z })[0]/*T:I!*/; } static void F(IIn x, IIn y) { var z = A.FIn/*T:IIn!*/; object o; o = (new[] { x, x })[0]/*T:IIn!*/; o = (new[] { x, y })[0]/*T:IIn!*/; o = (new[] { x, z })[0]/*T:IIn!*/; o = (new[] { y, x })[0]/*T:IIn!*/; o = (new[] { y, y })[0]/*T:IIn!*/; o = (new[] { y, z })[0]/*T:IIn!*/; o = (new[] { z, x })[0]/*T:IIn!*/; o = (new[] { z, y })[0]/*T:IIn!*/; o = (new[] { z, z })[0]/*T:IIn!*/; } static void F(IOut x, IOut y) { var z = A.FOut/*T:IOut!*/; object o; o = (new[] { x, x })[0]/*T:IOut!*/; o = (new[] { x, y })[0]/*T:IOut!*/; o = (new[] { x, z })[0]/*T:IOut!*/; o = (new[] { y, x })[0]/*T:IOut!*/; o = (new[] { y, y })[0]/*T:IOut!*/; o = (new[] { y, z })[0]/*T:IOut!*/; o = (new[] { z, x })[0]/*T:IOut!*/; o = (new[] { z, y })[0]/*T:IOut!*/; o = (new[] { z, z })[0]/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // o = (new[] { x, y })[0]/*T:I!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(8, 25), // (10,22): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // o = (new[] { y, x })[0]/*T:I!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(10, 22) ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_02() { var source0 = @"public class A { public static I F; public static IIn FIn; public static IOut FOut; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static I Create1(T t) => throw null!; static void G1(I> x1, I> y1) { var z1 = Create1(A.FOut)/*T:I!>!*/; object o; o = (new [] { x1, x1 })[0]/*T:I!>!*/; o = (new [] { x1, y1 })[0]/*T:I!>!*/; // 1 o = (new [] { x1, z1 })[0]/*T:I!>!*/; o = (new [] { y1, x1 })[0]/*T:I!>!*/; // 2 o = (new [] { y1, y1 })[0]/*T:I!>!*/; o = (new [] { y1, z1 })[0]/*T:I!>!*/; o = (new [] { z1, x1 })[0]/*T:I!>!*/; o = (new [] { z1, y1 })[0]/*T:I!>!*/; o = (new [] { z1, z1 })[0]/*T:I!>!*/; } static IOut Create2(T t) => throw null!; static void G2(IOut> x2, IOut> y2) { var z2 = Create2(A.FIn)/*T:IOut!>!*/; object o; o = (new [] { x2, x2 })[0]/*T:IOut!>!*/; o = (new [] { x2, y2 })[0]/*T:IOut!>!*/; o = (new [] { x2, z2 })[0]/*T:IOut!>!*/; o = (new [] { y2, x2 })[0]/*T:IOut!>!*/; o = (new [] { y2, y2 })[0]/*T:IOut!>!*/; o = (new [] { y2, z2 })[0]/*T:IOut!>!*/; o = (new [] { z2, x2 })[0]/*T:IOut!>!*/; o = (new [] { z2, y2 })[0]/*T:IOut!>!*/; o = (new [] { z2, z2 })[0]/*T:IOut!>!*/; } static IIn Create3(T t) => throw null!; static void G3(IIn> x3, IIn> y3) { var z3 = Create3(A.FOut)/*T:IIn!>!*/; object o; o = (new [] { x3, x3 })[0]/*T:IIn!>!*/; o = (new [] { x3, y3 })[0]/*T:IIn!>!*/; o = (new [] { x3, z3 })[0]/*T:IIn!>!*/; o = (new [] { y3, x3 })[0]/*T:IIn!>!*/; o = (new [] { y3, y3 })[0]/*T:IIn!>!*/; o = (new [] { y3, z3 })[0]/*T:IIn!>!*/; o = (new [] { z3, x3 })[0]/*T:IIn!>!*/; o = (new [] { z3, y3 })[0]/*T:IIn!>!*/; o = (new [] { z3, z3 })[0]/*T:IIn!>!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (10,23): warning CS8619: Nullability of reference types in value of type 'I>' doesn't match target type 'I>'. // o = (new [] { x1, y1 })[0]/*T:I!>!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I>", "I>").WithLocation(10, 23), // (12,27): warning CS8619: Nullability of reference types in value of type 'I>' doesn't match target type 'I>'. // o = (new [] { y1, x1 })[0]/*T:I!>!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I>", "I>").WithLocation(12, 27) ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] public void ImplicitlyTypedArrayCreation_NestedNullability_Variant_03() { var source0 = @"public class A { public static object F1; public static string F2; public static B.INone BON; public static B.I BOI; public static B.IIn BOIIn; public static B.IOut BOIOut; } public class B { public interface INone { } public interface I { } public interface IIn { } public interface IOut { } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static void G0(B.INone x0, B.INone y0) { var z0 = A.BON/*T:B.INone!*/; object o; o = (new[] { x0, x0 })[0]/*T:B.INone!*/; o = (new[] { x0, y0 })[0]/*T:B.INone!*/; // 1 o = (new[] { x0, z0 })[0]/*T:B.INone!*/; o = (new[] { y0, x0 })[0]/*T:B.INone!*/; // 2 o = (new[] { y0, y0 })[0]/*T:B.INone!*/; o = (new[] { y0, z0 })[0]/*T:B.INone!*/; o = (new[] { z0, x0 })[0]/*T:B.INone!*/; o = (new[] { z0, y0 })[0]/*T:B.INone!*/; o = (new[] { z0, z0 })[0]/*T:B.INone!*/; } static void G1(B.I x1, B.I y1) { var z1 = A.BOI/*T:B.I!*/; object o; o = (new[] { x1, x1 })[0]/*T:B.I!*/; o = (new[] { x1, y1 })[0]/*T:B.I!*/; // 3 o = (new[] { x1, z1 })[0]/*T:B.I!*/; o = (new[] { y1, x1 })[0]/*T:B.I!*/; // 4 o = (new[] { y1, y1 })[0]/*T:B.I!*/; o = (new[] { y1, z1 })[0]/*T:B.I!*/; o = (new[] { z1, x1 })[0]/*T:B.I!*/; o = (new[] { z1, y1 })[0]/*T:B.I!*/; o = (new[] { z1, z1 })[0]/*T:B.I!*/; } static void G2(B.IIn x2, B.IIn y2) { var z2 = A.BOIIn/*T:B.IIn!*/; object o; o = (new[] { x2, x2 })[0]/*T:B.IIn!*/; o = (new[] { x2, y2 })[0]/*T:B.IIn!*/; // 5 o = (new[] { x2, z2 })[0]/*T:B.IIn!*/; o = (new[] { y2, x2 })[0]/*T:B.IIn!*/; // 6 o = (new[] { y2, y2 })[0]/*T:B.IIn!*/; o = (new[] { y2, z2 })[0]/*T:B.IIn!*/; o = (new[] { z2, x2 })[0]/*T:B.IIn!*/; o = (new[] { z2, y2 })[0]/*T:B.IIn!*/; o = (new[] { z2, z2 })[0]/*T:B.IIn!*/; } static void G3(B.IOut x3, B.IOut y3) { var z3 = A.BOIOut/*T:B.IOut!*/; object o; o = (new[] { x3, x3 })[0]/*T:B.IOut!*/; o = (new[] { x3, y3 })[0]/*T:B.IOut!*/; // 7 o = (new[] { x3, z3 })[0]/*T:B.IOut!*/; o = (new[] { y3, x3 })[0]/*T:B.IOut!*/; // 8 o = (new[] { y3, y3 })[0]/*T:B.IOut!*/; o = (new[] { y3, z3 })[0]/*T:B.IOut!*/; o = (new[] { z3, x3 })[0]/*T:B.IOut!*/; o = (new[] { z3, y3 })[0]/*T:B.IOut!*/; o = (new[] { z3, z3 })[0]/*T:B.IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (9,26): warning CS8619: Nullability of reference types in value of type 'B.INone' doesn't match target type 'B.INone'. // o = (new[] { x0, y0 })[0]/*T:B.INone!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B.INone", "B.INone").WithLocation(9, 26), // (11,22): warning CS8619: Nullability of reference types in value of type 'B.INone' doesn't match target type 'B.INone'. // o = (new[] { y0, x0 })[0]/*T:B.INone!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B.INone", "B.INone").WithLocation(11, 22), // (23,26): warning CS8619: Nullability of reference types in value of type 'B.I' doesn't match target type 'B.I'. // o = (new[] { x1, y1 })[0]/*T:B.I!*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("B.I", "B.I").WithLocation(23, 26), // (25,22): warning CS8619: Nullability of reference types in value of type 'B.I' doesn't match target type 'B.I'. // o = (new[] { y1, x1 })[0]/*T:B.I!*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("B.I", "B.I").WithLocation(25, 22), // (37,26): warning CS8619: Nullability of reference types in value of type 'B.IIn' doesn't match target type 'B.IIn'. // o = (new[] { x2, y2 })[0]/*T:B.IIn!*/; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("B.IIn", "B.IIn").WithLocation(37, 26), // (39,22): warning CS8619: Nullability of reference types in value of type 'B.IIn' doesn't match target type 'B.IIn'. // o = (new[] { y2, x2 })[0]/*T:B.IIn!*/; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("B.IIn", "B.IIn").WithLocation(39, 22), // (51,26): warning CS8619: Nullability of reference types in value of type 'B.IOut' doesn't match target type 'B.IOut'. // o = (new[] { x3, y3 })[0]/*T:B.IOut!*/; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y3").WithArguments("B.IOut", "B.IOut").WithLocation(51, 26), // (53,22): warning CS8619: Nullability of reference types in value of type 'B.IOut' doesn't match target type 'B.IOut'. // o = (new[] { y3, x3 })[0]/*T:B.IOut!*/; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y3").WithArguments("B.IOut", "B.IOut").WithLocation(53, 22)); comp.VerifyTypes(); } [Fact] public void ImplicitlyTypedArrayCreation_NestedNullability_Tuples() { var source0 = @"public class A { public static object F; public static I IF; } public interface I { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F1(bool b, object x1, object? y1) { var z1 = A.F/*T:object!*/; object o; o = (new[] { (x1, x1), (x1, y1) })[0]/*T:(object!, object?)*/; o = (new[] { (z1, x1), (x1, x1) })[0]/*T:(object!, object!)*/; o = (new[] { (y1, y1), (y1, z1) })[0]/*T:(object?, object?)*/; o = (new[] { (x1, y1), (y1, y1) })[0]/*T:(object?, object?)*/; o = (new[] { (z1, z1), (z1, x1) })[0]/*T:(object!, object!)*/; o = (new[] { (y1, z1), (z1, z1) })[0]/*T:(object?, object!)*/; } static void F2(bool b, I x2, I y2) { var z2 = A.IF/*T:I!*/; object o; o = (new[] { (x2, x2), (x2, y2) })[0]/*T:(I!, I!)*/; // 1 o = (new[] { (z2, x2), (x2, x2) })[0]/*T:(I!, I!)*/; o = (new[] { (y2, y2), (y2, z2) })[0]/*T:(I!, I!)*/; o = (new[] { (x2, y2), (y2, y2) })[0]/*T:(I!, I!)*/; // 2 o = (new[] { (z2, z2), (z2, x2) })[0]/*T:(I!, I!)*/; o = (new[] { (y2, z2), (z2, z2) })[0]/*T:(I!, I!)*/; o = (new[] { (x2, x2)!, (x2, y2) })[0]/*T:(I!, I!)*/; // 3 o = (new[] { (x2, y2), (y2, y2)! })[0]/*T:(I!, I!)*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (18,32): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. // o = (new[] { (x2, x2), (x2, y2) })[0]/*T:(I!, I!)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(18, 32), // (21,32): warning CS8619: Nullability of reference types in value of type '(I, I)' doesn't match target type '(I, I)'. // o = (new[] { (x2, y2), (y2, y2) })[0]/*T:(I!, I!)*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(I, I)", "(I, I)").WithLocation(21, 32), // (25,33): warning CS8619: Nullability of reference types in value of type '(I x2, I y2)' doesn't match target type '(I, I)'. // o = (new[] { (x2, x2)!, (x2, y2) })[0]/*T:(I!, I!)*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x2, y2)").WithArguments("(I x2, I y2)", "(I, I)").WithLocation(25, 33)); comp.VerifyTypes(); } [Fact] public void ImplicitlyTypedArrayCreation_Empty() { var source = @"class Program { static void Main() { var a = new[] { }; var b = new[] { null }; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (5,17): error CS0826: No best type found for implicitly-typed array // var a = new[] { }; Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "new[] { }").WithLocation(5, 17), // (6,17): error CS0826: No best type found for implicitly-typed array // var b = new[] { null }; Diagnostic(ErrorCode.ERR_ImplicitlyTypedArrayNoBestType, "new[] { null }").WithLocation(6, 17)); } [Fact, WorkItem(36132, "https://github.com/dotnet/roslyn/issues/36132")] public void ImplicitlyTypedArrayCreation_UsesNullabilitiesOfConvertedTypes() { var source = @" class A { } class B { public static implicit operator A(B? b) => new A(); } class C { public static implicit operator A?(C c) => new A(); } class D { void Test(A a, B? b, C c) { _ = (new A[] { a, b }) /*T:A![]!*/; _ = (new A?[] { a, b }) /*T:A?[]!*/; _ = (new[] { a, b }) /*T:A![]!*/; _ = (new[] { b, a }) /*T:A![]!*/; _ = (new A[] { a, c }) /*T:A![]!*/; // 1 _ = (new A?[] { a, c }) /*T:A?[]!*/; _ = (new[] { a, c }) /*T:A?[]!*/; _ = (new[] { c, a }) /*T:A?[]!*/; } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics( // (15,27): warning CS8601: Possible null reference assignment. // _ = (new A[] { a, c }) /*T:A![]!*/; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c").WithLocation(15, 27) ); comp.VerifyTypes(); } [Fact, WorkItem(36132, "https://github.com/dotnet/roslyn/issues/36132")] public void Ternary_UsesNullabilitiesOfConvertedTypes() { var source = @" class A { } class B { public static implicit operator A(B? b) => new A(); } class C { public static implicit operator A?(C c) => new A(); } class D { void Test(A a, B? b, C c, bool cond) { _ = (cond ? a : b) /*T:A!*/; _ = (cond ? b : a) /*T:A!*/; _ = (cond ? a : c) /*T:A?*/; _ = (cond ? c : a) /*T:A?*/; } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact, WorkItem(36132, "https://github.com/dotnet/roslyn/issues/36132")] public void ReturnTypeInference_UsesNullabilitiesOfConvertedTypes() { var source = @" using System; class A { } class B { public static implicit operator A(B? b) => new A(); } class C { public static implicit operator A?(C c) => new A(); } class D { void Test(A a, B? b, C c, bool cond) { Func x1 = () => { if (cond) return a; else return b; }; Func x2 = () => { if (cond) return b; else return a; }; Func x3 = () => { if (cond) return a; else return c; }; Func x4 = () => { if (cond) return c; else return a; }; } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void ExplicitlyTypedArrayCreation() { var source = @"class C { static void F(object x, object? y) { var a = new object[] { x, y }; a[0].ToString(); var b = new object?[] { x, y }; b[0].ToString(); var c = new object[] { x, y! }; c[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,35): warning CS8601: Possible null reference assignment. // var a = new object[] { x, y }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(5, 35), // (8,9): warning CS8602: Dereference of a possibly null reference. // b[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(8, 9)); } [Fact] public void IdentityConversion_ArrayInitializer_02() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(I x, I y, I? z, I? w) { (new[] { x, y })[0].ToString(); // A1 (new[] { x, z })[0].ToString(); // A2 (new[] { x, w })[0].ToString(); // A3 (new[] { y, z })[0].ToString(); // A4 (new[] { y, w })[0].ToString(); // A5 (new[] { w, z })[0].ToString(); // A6 } static void F(IIn x, IIn y, IIn? z, IIn? w) { (new[] { x, y })[0].ToString(); // B1 (new[] { x, z })[0].ToString(); // B2 (new[] { x, w })[0].ToString(); // B3 (new[] { y, z })[0].ToString(); // B4 (new[] { y, w })[0].ToString(); // B5 (new[] { w, z })[0].ToString(); // B6 } static void F(IOut x, IOut y, IOut? z, IOut? w) { (new[] { x, y })[0].ToString(); // C1 (new[] { x, z })[0].ToString(); // C2 (new[] { x, w })[0].ToString(); // C3 (new[] { y, z })[0].ToString(); // C4 (new[] { y, w })[0].ToString(); // C5 (new[] { w, z })[0].ToString(); // C6 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,21): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // (new[] { x, y })[0].ToString(); // A1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(8, 21), // (9,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, z })[0].ToString(); // A2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, z })[0]").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, w })[0].ToString(); // A3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, w })[0]").WithLocation(10, 9), // (10,21): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // (new[] { x, w })[0].ToString(); // A3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("I", "I").WithLocation(10, 21), // (11,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, z })[0].ToString(); // A4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, z })[0]").WithLocation(11, 9), // (11,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // (new[] { y, z })[0].ToString(); // A4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(11, 18), // (12,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, w })[0].ToString(); // A5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, w })[0]").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // (new[] { w, z })[0].ToString(); // A6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { w, z })[0]").WithLocation(13, 9), // (13,18): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // (new[] { w, z })[0].ToString(); // A6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w").WithArguments("I", "I").WithLocation(13, 18), // (18,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, z })[0].ToString(); // B2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, z })[0]").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, w })[0].ToString(); // B3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, w })[0]").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, z })[0].ToString(); // B4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, z })[0]").WithLocation(20, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, w })[0].ToString(); // B5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, w })[0]").WithLocation(21, 9), // (22,9): warning CS8602: Dereference of a possibly null reference. // (new[] { w, z })[0].ToString(); // B6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { w, z })[0]").WithLocation(22, 9), // (27,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, z })[0].ToString(); // C2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, z })[0]").WithLocation(27, 9), // (28,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, w })[0].ToString(); // C3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, w })[0]").WithLocation(28, 9), // (29,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, z })[0].ToString(); // C4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, z })[0]").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, w })[0].ToString(); // C5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, w })[0]").WithLocation(30, 9), // (31,9): warning CS8602: Dereference of a possibly null reference. // (new[] { w, z })[0].ToString(); // C6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { w, z })[0]").WithLocation(31, 9) ); } [Fact] public void IdentityConversion_ArrayInitializer_IsNullableNull() { var source0 = @"#pragma warning disable 8618 public class A { public T F; } public class B : A { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F(object? x, B b) { var y = b.F/*T:object!*/; (new[] { x, x! })[0].ToString(); // 1 (new[] { x!, x })[0].ToString(); // 2 (new[] { x!, x! })[0].ToString(); (new[] { y, y! })[0].ToString(); (new[] { y!, y })[0].ToString(); (new[] { x, y })[0].ToString(); // 3 (new[] { x, y! })[0].ToString(); // 4 (new[] { x!, y })[0].ToString(); (new[] { x!, y! })[0].ToString(); } static void F(A z, B w) { (new[] { z, z! })[0].F.ToString(); // 5 (new[] { z!, z })[0].F.ToString(); // 6 (new[] { z!, z! })[0].F.ToString(); // 7 (new[] { w, w! })[0].F.ToString(); (new[] { w!, w })[0].F.ToString(); (new[] { z, w })[0].F.ToString(); // 8 (new[] { z, w! })[0].F.ToString(); // 9 (new[] { z!, w })[0].F.ToString(); // 10 (new[] { z!, w! })[0].F.ToString(); // 11 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); // https://github.com/dotnet/roslyn/issues/30376: `!` should suppress conversion warnings. comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, x! })[0].ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, x! })[0]").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x!, x })[0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x!, x })[0]").WithLocation(7, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, y })[0].ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, y })[0]").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, y! })[0].ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, y! })[0]").WithLocation(12, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z, z! })[0].F.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z, z! })[0].F").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z!, z })[0].F.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z!, z })[0].F").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z!, z! })[0].F.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z!, z! })[0].F").WithLocation(20, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z, w })[0].F.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z, w })[0].F").WithLocation(23, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z, w! })[0].F.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z, w! })[0].F").WithLocation(24, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z!, w })[0].F.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z!, w })[0].F").WithLocation(25, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // (new[] { z!, w! })[0].F.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z!, w! })[0].F").WithLocation(26, 9)); } [Fact] public void IdentityConversion_ArrayInitializer_ExplicitType() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(I? x, I? y) { I?[] a = new[] { x }; I[] b = new[] { y }; I?[] c = new[] { y }; I[] d = new[] { x }; } static void F(IIn? x, IIn? y) { IIn?[] a = new[] { x }; IIn[] b = new[] { y }; IIn?[] c = new[] { y }; IIn[] d = new[] { x }; } static void F(IOut? x, IOut? y) { IOut?[] a = new[] { x }; IOut[] b = new[] { y }; IOut?[] c = new[] { y }; IOut[] d = new[] { x }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,27): warning CS8619: Nullability of reference types in value of type 'I?[]' doesn't match target type 'I?[]'. // I?[] a = new[] { x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { x }").WithArguments("I?[]", "I?[]").WithLocation(8, 27), // (9,26): warning CS8619: Nullability of reference types in value of type 'I?[]' doesn't match target type 'I[]'. // I[] b = new[] { y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { y }").WithArguments("I?[]", "I[]").WithLocation(9, 26), // (10,26): warning CS8619: Nullability of reference types in value of type 'I?[]' doesn't match target type 'I?[]'. // I?[] c = new[] { y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { y }").WithArguments("I?[]", "I?[]").WithLocation(10, 26), // (11,25): warning CS8619: Nullability of reference types in value of type 'I?[]' doesn't match target type 'I[]'. // I[] d = new[] { x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { x }").WithArguments("I?[]", "I[]").WithLocation(11, 25), // (15,29): warning CS8619: Nullability of reference types in value of type 'IIn?[]' doesn't match target type 'IIn?[]'. // IIn?[] a = new[] { x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { x }").WithArguments("IIn?[]", "IIn?[]").WithLocation(15, 29), // (16,28): warning CS8619: Nullability of reference types in value of type 'IIn?[]' doesn't match target type 'IIn[]'. // IIn[] b = new[] { y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { y }").WithArguments("IIn?[]", "IIn[]").WithLocation(16, 28), // (18,27): warning CS8619: Nullability of reference types in value of type 'IIn?[]' doesn't match target type 'IIn[]'. // IIn[] d = new[] { x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { x }").WithArguments("IIn?[]", "IIn[]").WithLocation(18, 27), // (23,29): warning CS8619: Nullability of reference types in value of type 'IOut?[]' doesn't match target type 'IOut[]'. // IOut[] b = new[] { y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { y }").WithArguments("IOut?[]", "IOut[]").WithLocation(23, 29), // (24,29): warning CS8619: Nullability of reference types in value of type 'IOut?[]' doesn't match target type 'IOut?[]'. // IOut?[] c = new[] { y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { y }").WithArguments("IOut?[]", "IOut?[]").WithLocation(24, 29), // (25,28): warning CS8619: Nullability of reference types in value of type 'IOut?[]' doesn't match target type 'IOut[]'. // IOut[] d = new[] { x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new[] { x }").WithArguments("IOut?[]", "IOut[]").WithLocation(25, 28)); } [Fact] public void ImplicitConversion_ArrayInitializer_ExplicitType_01() { var source = @"class A { } class B : A { } class C { static void F(A x, B y) { var z = new A[] { x, y }; var w = new A[] { x, y }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,38): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // var z = new A[] { x, y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("B", "A").WithLocation(7, 38), // (8,36): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // var w = new A[] { x, y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "A").WithLocation(8, 36)); } [Fact] public void ImplicitConversion_ArrayInitializer_ExplicitType_02() { var source = @"interface IIn { } interface IOut { } class C { static void F(IIn x, IIn y) { var a = new IIn[] { x }; var b = new IIn[] { y }; } static void F(IOut x, IOut y) { var a = new IOut[] { x }; var b = new IOut[] { y }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,38): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // var a = new IIn[] { x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(7, 38), // (13,38): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // var b = new IOut[] { y }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(13, 38)); } [Fact] public void MultipleConversions_ArrayInitializer() { var source = @"class A { public static implicit operator C(A a) => new C(); } class B : A { } class C { static void F(B x, C? y) { (new[] { x, y })[0].ToString(); (new[] { y, x })[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, y })[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, y })[0]").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, x })[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, x })[0]").WithLocation(13, 9)); } [Fact] public void MultipleConversions_ArrayInitializer_ConversionWithNullableOutput() { var source = @"class A { public static implicit operator C?(A a) => new C(); } class B : A { } class C { static void F(B x, C y) { (new[] { x, y })[0].ToString(); (new[] { y, x })[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // (new[] { x, y })[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, y })[0]").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // (new[] { y, x })[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { y, x })[0]").WithLocation(13, 9)); } [Fact] public void MultipleConversions_ArrayInitializer_ConversionWithNullableInput() { var source = @"class A { public static implicit operator C(A? a) => new C(); } class B : A { } class C { static void F(B? x, C y) { (new[] { x, y })[0].ToString(); (new[] { y, x })[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ObjectInitializer_01() { CSharpCompilation c = CreateCompilation( new[] { @"#pragma warning disable 8618 class C { static void Main() {} void Test1(CL1? x1, CL1? y1) { var z1 = new CL1() { F1 = x1, F2 = y1 }; } void Test2(CL1? x2, CL1? y2) { var z2 = new CL1() { P1 = x2, P2 = y2 }; } void Test3(CL1 x3, CL1 y3) { var z31 = new CL1() { F1 = x3, F2 = y3 }; var z32 = new CL1() { P1 = x3, P2 = y3 }; } } class CL1 { public CL1 F1; public CL1? F2; public CL1 P1 {get; set;} public CL1? P2 {get; set;} } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,35): warning CS8601: Possible null reference assignment. // var z1 = new CL1() { F1 = x1, F2 = y1 }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x1").WithLocation(9, 35), // (14,35): warning CS8601: Possible null reference assignment. // var z2 = new CL1() { P1 = x2, P2 = y2 }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x2").WithLocation(14, 35) ); } [Fact] public void ObjectInitializer_02() { var source = @"class C { C(object o) { } static void F(object? x) { var y = new C(x); if (x != null) y = new C(x); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,23): warning CS8604: Possible null reference argument for parameter 'o' in 'C.C(object o)'. // var y = new C(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("o", "C.C(object o)").WithLocation(6, 23)); } [Fact] public void ObjectInitializer_03() { var source = @"class A { internal B F = new B(); } class B { internal object? G; } class C { static void Main() { var o = new A() { F = { G = new object() } }; o.F.G.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void IdentityConversion_ObjectElementInitializerArgumentsOrder() { var source = @"interface I { } class C { static C F(I x, I y) { return new C() { [ y: y, // warn 1 x: x] = 1 }; } static object G(C c, I x, I y) { return new C() { [ y: y, x: x] // warn 2 = 2 }; } int this[I x, I y] { get { return 0; } set { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,16): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'int C.this[I x, I y]'. // y: y, // warn 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "y", "int C.this[I x, I y]").WithLocation(7, 16), // (15,16): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'int C.this[I x, I y]'. // x: x] // warn 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "int C.this[I x, I y]").WithLocation(15, 16)); } [Fact] public void ImplicitConversion_CollectionInitializer() { var source = @"using System.Collections.Generic; class A { } class B : A { } class C { static void M(B? x, B y) { var c = new List> { x, // 1 y, // 2 }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8604: Possible null reference argument for parameter 'item' in 'void List>.Add(A item)'. // x, // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("item", "void List>.Add(A item)").WithLocation(10, 13), // (11,13): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'A' for parameter 'item' in 'void List>.Add(A item)'. // y, // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "A", "item", "void List>.Add(A item)").WithLocation(11, 13)); } [Fact] public void Structs_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL1 x1) { S1 y1 = new S1(); y1.F1 = x1; y1 = new S1(); x1 = y1.F1; } void M1(ref S1 x) {} void Test2(CL1 x2) { S1 y2 = new S1(); y2.F1 = x2; M1(ref y2); x2 = y2.F1; } void Test3(CL1 x3) { S1 y3 = new S1() { F1 = x3 }; x3 = y3.F1; } void Test4(CL1 x4, CL1? z4) { var y4 = new S2() { F2 = new S1() { F1 = x4, F3 = z4 } }; x4 = y4.F2.F1 ?? x4; x4 = y4.F2.F3; } void Test5(CL1 x5, CL1? z5) { var y5 = new S2() { F2 = new S1() { F1 = x5, F3 = z5 } }; var u5 = y5.F2; x5 = u5.F1 ?? x5; x5 = u5.F3; } } class CL1 { } struct S1 { public CL1? F1; public CL1? F3; } struct S2 { public S1 F2; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = y1.F1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1.F1").WithLocation(12, 14), // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = y2.F1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y2.F1").WithLocation(22, 14), // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = y4.F2.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y4.F2.F3").WithLocation(35, 14), // (43,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = u5.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u5.F3").WithLocation(43, 14) ); } [Fact] public void Structs_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL1 x1) { S1 y1; y1.F1 = x1; S1 z1 = y1; x1 = z1.F3; x1 = z1.F3 ?? x1; z1.F3 = null; } struct Test2 { S1 z2 {get;} public Test2(CL1 x2) { S1 y2; y2.F1 = x2; z2 = y2; x2 = z2.F3; x2 = z2.F3 ?? x2; } } void Test3(CL1 x3) { S1 y3; CL1? z3 = y3.F3; x3 = z3; x3 = z3 ?? x3; } void Test4(CL1 x4, CL1? z4) { S1 y4; z4 = y4.F3; x4 = z4; x4 = z4 ?? x4; } void Test5(CL1 x5) { S1 y5; var z5 = new { F3 = y5.F3 }; x5 = z5.F3; x5 = z5.F3 ?? x5; } void Test6(CL1 x6, S1 z6) { S1 y6; y6.F1 = x6; z6 = y6; x6 = z6.F3; x6 = z6.F3 ?? x6; } void Test7(CL1 x7) { S1 y7; y7.F1 = x7; var z7 = new { F3 = y7 }; x7 = z7.F3.F3; x7 = z7.F3.F3 ?? x7; } struct Test8 { CL1? z8 {get;} public Test8(CL1 x8) { S1 y8; y8.F1 = x8; z8 = y8.F3; x8 = z8; x8 = z8 ?? x8; } } } class CL1 { } struct S1 { public CL1? F1; public CL1? F3; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,17): error CS0165: Use of unassigned local variable 'y1' // S1 z1 = y1; Diagnostic(ErrorCode.ERR_UseDefViolation, "y1").WithArguments("y1").WithLocation(11, 17), // (12,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = z1.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z1.F3").WithLocation(12, 14), // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = z1.F3 ?? x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z1.F3 ?? x1").WithLocation(13, 14), // (25,18): error CS0165: Use of unassigned local variable 'y2' // z2 = y2; Diagnostic(ErrorCode.ERR_UseDefViolation, "y2").WithArguments("y2").WithLocation(25, 18), // (26,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = z2.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z2.F3").WithLocation(26, 18), // (27,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = z2.F3 ?? x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z2.F3 ?? x2").WithLocation(27, 18), // (34,19): error CS0170: Use of possibly unassigned field 'F3' // CL1? z3 = y3.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y3.F3").WithArguments("F3").WithLocation(34, 19), // (35,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = z3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z3").WithLocation(35, 14), // (36,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = z3 ?? x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z3 ?? x3").WithLocation(36, 14), // (42,14): error CS0170: Use of possibly unassigned field 'F3' // z4 = y4.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y4.F3").WithArguments("F3").WithLocation(42, 14), // (43,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = z4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z4").WithLocation(43, 14), // (44,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = z4 ?? x4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z4 ?? x4").WithLocation(44, 14), // (50,29): error CS0170: Use of possibly unassigned field 'F3' // var z5 = new { F3 = y5.F3 }; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y5.F3").WithArguments("F3").WithLocation(50, 29), // (51,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = z5.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z5.F3").WithLocation(51, 14), // (52,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = z5.F3 ?? x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z5.F3 ?? x5").WithLocation(52, 14), // (59,14): error CS0165: Use of unassigned local variable 'y6' // z6 = y6; Diagnostic(ErrorCode.ERR_UseDefViolation, "y6").WithArguments("y6").WithLocation(59, 14), // (60,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x6 = z6.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z6.F3").WithLocation(60, 14), // (61,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x6 = z6.F3 ?? x6; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z6.F3 ?? x6").WithLocation(61, 14), // (68,29): error CS0165: Use of unassigned local variable 'y7' // var z7 = new { F3 = y7 }; Diagnostic(ErrorCode.ERR_UseDefViolation, "y7").WithArguments("y7").WithLocation(68, 29), // (69,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = z7.F3.F3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z7.F3.F3").WithLocation(69, 14), // (70,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = z7.F3.F3 ?? x7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z7.F3.F3 ?? x7").WithLocation(70, 14), // (81,18): error CS0170: Use of possibly unassigned field 'F3' // z8 = y8.F3; Diagnostic(ErrorCode.ERR_UseDefViolationField, "y8.F3").WithArguments("F3").WithLocation(81, 18), // (82,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x8 = z8; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z8").WithLocation(82, 18), // (83,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // x8 = z8 ?? x8; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z8 ?? x8").WithLocation(83, 18) ); } [Fact] public void Structs_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL1 x1) { x1 = new S1().F1; } void Test2(CL1 x2) { x2 = new S1() {F1 = x2}.F1; } void Test3(CL1 x3) { x3 = new S1() {F1 = x3}.F1 ?? x3; } void Test4(CL1 x4) { x4 = new S2().F2; } void Test5(CL1 x5) { x5 = new S2().F2 ?? x5; } } class CL1 { } struct S1 { public CL1? F1; } struct S2 { public CL1 F2; S2(CL1 x) { F2 = x; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = new S1().F1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "new S1().F1").WithLocation(9, 14), // (24,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = new S2().F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "new S2().F2").WithLocation(24, 14) ); } [Fact] public void Structs_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} } struct TS2 { System.Action? E2; TS2(System.Action x2) { this = new TS2(); System.Action z2 = E2; System.Action y2 = E2 ?? x2; } void Dummy() { E2 = null; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action z2 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(15, 28) ); } [Fact] [WorkItem(29889, "https://github.com/dotnet/roslyn/issues/29889")] public void AnonymousTypes_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL1 x1, CL1? z1) { var y1 = new { p1 = x1, p2 = z1 }; x1 = y1.p1 ?? x1; x1 = y1.p2; } void Test2(CL1 x2, CL1? z2) { var u2 = new { p1 = x2, p2 = z2 }; var v2 = new { p1 = z2, p2 = x2 }; u2 = v2; x2 = u2.p2 ?? x2; x2 = u2.p1; x2 = v2.p2 ?? x2; x2 = v2.p1; } void Test3(CL1 x3, CL1? z3) { var u3 = new { p1 = x3, p2 = z3 }; var v3 = u3; x3 = v3.p1 ?? x3; x3 = v3.p2; } void Test4(CL1 x4, CL1? z4) { var u4 = new { p0 = new { p1 = x4, p2 = z4 } }; var v4 = new { p0 = new { p1 = z4, p2 = x4 } }; u4 = v4; x4 = u4.p0.p2 ?? x4; x4 = u4.p0.p1; x4 = v4.p0.p2 ?? x4; x4 = v4.p0.p1; } void Test5(CL1 x5, CL1? z5) { var u5 = new { p0 = new { p1 = x5, p2 = z5 } }; var v5 = u5; x5 = v5.p0.p1 ?? x5; x5 = v5.p0.p2; } void Test6(CL1 x6, CL1? z6) { var u6 = new { p0 = new { p1 = x6, p2 = z6 } }; var v6 = u6.p0; x6 = v6.p1 ?? x6; x6 = v6.p2; } void Test7(CL1 x7, CL1? z7) { var u7 = new { p0 = new S1() { p1 = x7, p2 = z7 } }; var v7 = new { p0 = new S1() { p1 = z7, p2 = x7 } }; u7 = v7; x7 = u7.p0.p2 ?? x7; x7 = u7.p0.p1; x7 = v7.p0.p2 ?? x7; x7 = v7.p0.p1; } void Test8(CL1 x8, CL1? z8) { var u8 = new { p0 = new S1() { p1 = x8, p2 = z8 } }; var v8 = u8; x8 = v8.p0.p1 ?? x8; x8 = v8.p0.p2; } void Test9(CL1 x9, CL1? z9) { var u9 = new { p0 = new S1() { p1 = x9, p2 = z9 } }; var v9 = u9.p0; x9 = v9.p1 ?? x9; x9 = v9.p2; } void M1(ref T x) {} void Test10(CL1 x10) { var u10 = new { a0 = x10, a1 = new { p1 = x10 }, a2 = new S1() { p2 = x10 } }; x10 = u10.a0; // 1 x10 = u10.a1.p1; // 2 x10 = u10.a2.p2; // 3 M1(ref u10); x10 = u10.a0; // 4 x10 = u10.a1.p1; // 5 x10 = u10.a2.p2; // 6 } } class CL1 { } struct S1 { public CL1? p1; public CL1? p2; }" }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = y1.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1.p2").WithLocation(11, 14), // (18,14): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. // u2 = v2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "v2").WithArguments("", "").WithLocation(18, 14), // (20,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = u2.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u2.p1").WithLocation(20, 14), // (21,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = v2.p2 ?? x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v2.p2 ?? x2").WithLocation(21, 14), // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = v2.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v2.p1").WithLocation(22, 14), // (30,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = v3.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v3.p2").WithLocation(30, 14), // (37,14): warning CS8619: Nullability of reference types in value of type ' p0>' doesn't match target type ' p0>'. // u4 = v4; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "v4").WithArguments(" p0>", " p0>").WithLocation(37, 14), // (39,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = u4.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u4.p0.p1").WithLocation(39, 14), // (40,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = v4.p0.p2 ?? x4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v4.p0.p2 ?? x4").WithLocation(40, 14), // (41,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x4 = v4.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v4.p0.p1").WithLocation(41, 14), // (49,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x5 = v5.p0.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v5.p0.p2").WithLocation(49, 14), // (57,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x6 = v6.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v6.p2").WithLocation(57, 14), // (66,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = u7.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u7.p0.p1").WithLocation(66, 14), // (67,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = v7.p0.p2 ?? x7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v7.p0.p2 ?? x7").WithLocation(67, 14), // (68,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x7 = v7.p0.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v7.p0.p1").WithLocation(68, 14), // (76,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x8 = v8.p0.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v8.p0.p2").WithLocation(76, 14), // (84,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x9 = v9.p2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "v9.p2").WithLocation(84, 14), // (100,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // x10 = u10.a2.p2; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u10.a2.p2").WithLocation(100, 15)); } [Fact] public void AnonymousTypes_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL1? x1) { var y1 = new { p1 = x1 }; y1.p1?. M1(y1.p1); } void Test2(CL1? x2) { var y2 = new { p1 = x2 }; if (y2.p1 != null) { y2.p1.M1(y2.p1); } } void Test3(out CL1? x3, CL1 z3) { var y3 = new { p1 = x3 }; x3 = y3.p1 ?? z3.M1(y3.p1); CL1 v3 = y3.p1; } } class CL1 { public CL1? M1(CL1 x) { return null; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (25,29): error CS0269: Use of unassigned out parameter 'x3' // var y3 = new { p1 = x3 }; Diagnostic(ErrorCode.ERR_UseDefViolationOut, "x3").WithArguments("x3").WithLocation(25, 29), // (27,29): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1? CL1.M1(CL1 x)'. // z3.M1(y3.p1); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y3.p1").WithArguments("x", "CL1? CL1.M1(CL1 x)").WithLocation(27, 29), // (28,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 v3 = y3.p1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y3.p1").WithLocation(28, 18)); } [Fact] public void AnonymousTypes_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test2(CL1 x2) { x2 = new {F1 = x2}.F1; } void Test3(CL1 x3) { x3 = new {F1 = x3}.F1 ?? x3; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void AnonymousTypes_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL1 x1, CL1 y1) { var u1 = new { F1 = x1 }; var v1 = new { F1 = y1 }; u1 = v1; v1 = u1; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,14): warning CS8619: Nullability of reference types in value of type ' F1>' doesn't match target type ' F1>'. // u1 = v1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "v1").WithArguments(" F1>", " F1>").WithLocation(12, 14), // (13,14): warning CS8619: Nullability of reference types in value of type ' F1>' doesn't match target type ' F1>'. // v1 = u1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "u1").WithArguments(" F1>", " F1>").WithLocation(13, 14) ); } [Fact] [WorkItem(29889, "https://github.com/dotnet/roslyn/issues/29889")] [WorkItem(33577, "https://github.com/dotnet/roslyn/issues/33577")] public void AnonymousTypes_05() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F0(string x0, string? y0) { var a0 = new { F = x0 }; var b0 = new { F = y0 }; a0 = b0; // 1 b0 = a0; // 2 } static void F1(I x1, I y1) { var a1 = new { F = x1 }; var b1 = new { F = y1 }; a1 = b1; // 3 b1 = a1; // 4 } static void F2(IIn x2, IIn y2) { var a2 = new { F = x2 }; var b2 = new { F = y2 }; a2 = b2; b2 = a2; // 5 } static void F3(IOut x3, IOut y3) { var a3 = new { F = x3 }; var b3 = new { F = y3 }; a3 = b3; // 6 b3 = a3; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/33577: Should not report a warning for `a2 = b2` or `b3 = a3`. comp.VerifyDiagnostics( // (10,14): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. // a0 = b0; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b0").WithArguments("", "").WithLocation(10, 14), // (11,14): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. // b0 = a0; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a0").WithArguments("", "").WithLocation(11, 14), // (17,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // a1 = b1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b1").WithArguments(" F>", " F>").WithLocation(17, 14), // (18,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // b1 = a1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a1").WithArguments(" F>", " F>").WithLocation(18, 14), // (24,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // a2 = b2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b2").WithArguments(" F>", " F>").WithLocation(24, 14), // (25,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // b2 = a2; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments(" F>", " F>").WithLocation(25, 14), // (31,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // a3 = b3; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b3").WithArguments(" F>", " F>").WithLocation(31, 14), // (32,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // b3 = a3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a3").WithArguments(" F>", " F>").WithLocation(32, 14)); } [Fact] [WorkItem(29890, "https://github.com/dotnet/roslyn/issues/29890")] public void AnonymousTypes_06() { var source = @"class C { static void F(string x, string y) { x = new { x, y }.x ?? x; y = new { x, y = y }.y ?? y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void AnonymousTypes_07() { var source = @"class Program { static T F(T t) => t; static void G() { var a = new { }; a = new { }; a = F(a); a = F(new { }); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] public void AnonymousTypes_08() { var source = @"class Program { static void F(T x, T? y) where T : class { new { x, y }.x.ToString(); new { x, y }.y.ToString(); // 1 new { y, x }.x.ToString(); new { y, x }.y.ToString(); // 2 new { x = x, y = y }.x.ToString(); new { x = x, y = y }.y.ToString(); // 3 new { x = y, y = x }.x.ToString(); // 4 new { x = y, y = x }.y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // new { x, y }.y.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new { x, y }.y").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // new { y, x }.y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new { y, x }.y").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // new { x = x, y = y }.y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new { x = x, y = y }.y").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // new { x = y, y = x }.x.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new { x = y, y = x }.x").WithLocation(11, 9)); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] public void AnonymousTypes_09() { var source = @"class Program { static void F(T? x, T? y) where T : struct { if (y == null) return; _ = new { x = x, y = y }.x.Value; // 1 _ = new { x = x, y = y }.y.Value; _ = new { x = y, y = x }.x.Value; _ = new { x = y, y = x }.y.Value; // 2 _ = new { x, y }.x.Value; // 3 _ = new { x, y }.y.Value; _ = new { y, x }.x.Value; // 4 _ = new { y, x }.y.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = new { x = x, y = y }.x.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x = x, y = y }.x").WithLocation(6, 13), // (9,13): warning CS8629: Nullable value type may be null. // _ = new { x = y, y = x }.y.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x = y, y = x }.y").WithLocation(9, 13), // (10,13): warning CS8629: Nullable value type may be null. // _ = new { x, y }.x.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { x, y }.x").WithLocation(10, 13), // (12,13): warning CS8629: Nullable value type may be null. // _ = new { y, x }.x.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new { y, x }.x").WithLocation(12, 13)); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] public void AnonymousTypes_10() { var source = @"class Program { static void F(T x, T? y) where T : class { var a = new { x, y }; a.x/*T:T!*/.ToString(); a.y/*T:T?*/.ToString(); // 1 a = new { x = y, y = x }; // 2 a.x/*T:T?*/.ToString(); // 3 a.y/*T:T!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // a.y/*T:T?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.y").WithLocation(7, 9), // (8,13): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. // a = new { x = y, y = x }; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new { x = y, y = x }").WithArguments("", "").WithLocation(8, 13), // (9,9): warning CS8602: Dereference of a possibly null reference. // a.x/*T:T?*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.x").WithLocation(9, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] [WorkItem(33577, "https://github.com/dotnet/roslyn/issues/33577")] public void AnonymousTypes_11() { var source = @"class Program { static void F() where T : struct { T? x = new T(); T? y = null; var a = new { x, y }; _ = a.x.Value; _ = a.y.Value; // 1 x = null; y = new T(); a = new { x, y }; _ = a.x.Value; // 2 _ = a.y.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8629: Nullable value type may be null. // _ = a.y.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a.y").WithLocation(9, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = a.x.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a.x").WithLocation(13, 13)); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] public void AnonymousTypes_12() { var source = @"class Program { static void F() where T : class, new() { T x = null; // 1 T? y = new T(); var a = new { x, y }; a.x/*T:T?*/.ToString(); // 2 a.y/*T:T!*/.ToString(); x = new T(); y = null; a = new { x, y }; // 3 a.x/*T:T!*/.ToString(); a.y/*T:T?*/.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 15), // (8,9): warning CS8602: Dereference of a possibly null reference. // a.x/*T:T?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.x").WithLocation(8, 9), // (12,13): warning CS8619: Nullability of reference types in value of type '' doesn't match target type ''. // a = new { x, y }; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new { x, y }").WithArguments("", "").WithLocation(12, 13), // (14,9): warning CS8602: Dereference of a possibly null reference. // a.y/*T:T?*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.y").WithLocation(14, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] public void AnonymousTypes_13() { var source = @"class Program { static void F(T x, T y) { } static void G(T x, T? y) where T : class { F(new { x, y }, new { x = x, y = y }); F(new { x, y }, new { x = y, y = x }); // 1 F(new { x = x, y = y }, new { x = x, y = y }); F(new { x = x, y = y }, new { x = y, y = x }); // 2 F(new { x = x, y = y }, new { x, y }); F(new { x = y, y = x }, new { x, y }); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,25): warning CS8620: Nullability of reference types in argument of type '' doesn't match target type '' for parameter 'y' in 'void Program.F<>( x, y)'. // F(new { x, y }, new { x = y, y = x }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new { x = y, y = x }").WithArguments("", "", "y", "void Program.F<>( x, y)").WithLocation(9, 25), // (11,33): warning CS8620: Nullability of reference types in argument of type '' doesn't match target type '' for parameter 'y' in 'void Program.F<>( x, y)'. // F(new { x = x, y = y }, new { x = y, y = x }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new { x = y, y = x }").WithArguments("", "", "y", "void Program.F<>( x, y)").WithLocation(11, 33), // (13,33): warning CS8620: Nullability of reference types in argument of type '' doesn't match target type '' for parameter 'y' in 'void Program.F<>( x, y)'. // F(new { x = y, y = x }, new { x, y }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "new { x, y }").WithArguments("", "", "y", "void Program.F<>( x, y)").WithLocation(13, 33)); } [Fact] [WorkItem(33007, "https://github.com/dotnet/roslyn/issues/33007")] public void AnonymousTypes_14() { var source = @"class Program { static T F(T t) => t; static void F1(T t1) where T : class { var a1 = F(new { t = t1 }); a1.t.ToString(); } static void F2(T? t2) where T : class { var a2 = F(new { t = t2 }); a2.t.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // a2.t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2.t").WithLocation(12, 9)); } [Fact] [WorkItem(33007, "https://github.com/dotnet/roslyn/issues/33007")] public void AnonymousTypes_15() { var source = @"using System; class Program { static U F(Func f, T t) => f(t); static void F1(T t1) where T : class { var a1 = F(t => new { t }, t1); a1.t.ToString(); } static void F2(T? t2) where T : class { var a2 = F(t => new { t }, t2); a2.t.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // a2.t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2.t").WithLocation(13, 9)); } [Fact] [WorkItem(24018, "https://github.com/dotnet/roslyn/issues/24018")] public void AnonymousTypes_16() { var source = @"class Program { static void F(T? t) where T : class { new { }.Missing(); if (t == null) return; new { t }.Missing(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,17): error CS1061: '' does not contain a definition for 'Missing' and no accessible extension method 'Missing' accepting a first argument of type '' could be found (are you missing a using directive or an assembly reference?) // new { }.Missing(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Missing").WithArguments("", "Missing").WithLocation(5, 17), // (7,19): error CS1061: '' does not contain a definition for 'Missing' and no accessible extension method 'Missing' accepting a first argument of type '' could be found (are you missing a using directive or an assembly reference?) // new { t }.Missing(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Missing").WithArguments("", "Missing").WithLocation(7, 19)); } [Fact] public void AnonymousObjectCreation_01() { var source = @"class C { static void F(object? o) { (new { P = o }).P.ToString(); if (o == null) return; (new { Q = o }).Q.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // (new { P = o }).P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new { P = o }).P").WithLocation(5, 9)); } [Fact] [WorkItem(29891, "https://github.com/dotnet/roslyn/issues/29891")] public void AnonymousObjectCreation_02() { var source = @"class C { static void F(object? o) { (new { P = new[] { o }}).P[0].ToString(); if (o == null) return; (new { Q = new[] { o }}).Q[0].ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // (new { P = new[] { o }}).P[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new { P = new[] { o }}).P[0]").WithLocation(5, 9)); } [Fact] public void This() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1() { this.Test2(); } void Test2() { this?.Test1(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void ReadonlyAutoProperties_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C1 { static void Main() { } C1 P1 {get;} public C1(C1? x1) { P1 = x1; } } class C2 { C2? P2 {get;} public C2(C2 x2) { x2 = P2; } } class C3 { C3? P3 {get;} public C3(C3 x3, C3? y3) { P3 = y3; x3 = P3; } } class C4 { C4? P4 {get;} public C4(C4 x4) { P4 = x4; x4 = P4; } } class C5 { S1 P5 {get;} public C5(C0 x5) { P5 = new S1() { F1 = x5 }; x5 = P5.F1; } } class C0 {} struct S1 { public C0? F1; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P2").WithLocation(22, 14), // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = P3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P3").WithLocation(33, 14), // (12,14): warning CS8601: Possible null reference assignment. // P1 = x1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x1").WithLocation(12, 14) ); } [Fact] public void ReadonlyAutoProperties_02() { CSharpCompilation c = CreateCompilation(new[] { @" struct C1 { static void Main() { } C0 P1 {get;} public C1(C0? x1) { P1 = x1; } } struct C2 { C0? P2 {get;} public C2(C0 x2) { x2 = P2; P2 = null; } } struct C3 { C0? P3 {get;} public C3(C0 x3, C0? y3) { P3 = y3; x3 = P3; } } struct C4 { C0? P4 {get;} public C4(C0 x4) { P4 = x4; x4 = P4; } } struct C5 { S1 P5 {get;} public C5(C0 x5) { P5 = new S1() { F1 = x5 }; x5 = P5.F1 ?? x5; } } class C0 {} struct S1 { public C0? F1; } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (34,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = P3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P3").WithLocation(34, 14), // (22,14): error CS8079: Use of possibly unassigned auto-implemented property 'P2' // x2 = P2; Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "P2").WithArguments("P2").WithLocation(22, 14), // (22,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P2").WithLocation(22, 14), // (12,14): warning CS8601: Possible null reference assignment. // P1 = x1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x1").WithLocation(12, 14) ); } [Fact] public void NotAssigned() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(object? x1) { CL1? y1; if (x1 == null) { y1 = null; return; } CL1 z1 = y1; } void Test2(object? x2, out CL1? y2) { if (x2 == null) { y2 = null; return; } CL1 z2 = y2; y2 = null; } } class CL1 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (17,18): error CS0165: Use of unassigned local variable 'y1' // CL1 z1 = y1; Diagnostic(ErrorCode.ERR_UseDefViolation, "y1").WithArguments("y1").WithLocation(17, 18), // (28,18): error CS0269: Use of unassigned out parameter 'y2' // CL1 z2 = y2; Diagnostic(ErrorCode.ERR_UseDefViolationOut, "y2").WithArguments("y2").WithLocation(28, 18) ); } [Fact] public void Lambda_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Func x1 = () => M1(); } void Test2() { System.Func x2 = delegate { return M1(); }; } delegate CL1? D1(); void Test3() { D1 x3 = () => M1(); } void Test4() { D1 x4 = delegate { return M1(); }; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Lambda_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Action x1 = (p1) => p1 = M1(); } delegate void D1(CL1? p); void Test3() { D1 x3 = (p3) => p3 = M1(); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Lambda_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Func x1 = () => M1(); } void Test2() { System.Func x2 = delegate { return M1(); }; } delegate CL1 D1(); void Test3() { D1 x3 = () => M1(); } void Test4() { D1 x4 = delegate { return M1(); }; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,37): warning CS8603: Possible null reference return. // System.Func x1 = () => M1(); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(12, 37), // (17,49): warning CS8603: Possible null reference return. // System.Func x2 = delegate { return M1(); }; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(17, 49), // (24,23): warning CS8603: Possible null reference return. // D1 x3 = () => M1(); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(24, 23), // (29,35): warning CS8603: Possible null reference return. // D1 x4 = delegate { return M1(); }; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(29, 35) ); } [Fact] public void Lambda_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Action x1 = (p1) => p1 = M1(); } delegate void D1(CL1 p); void Test3() { D1 x3 = (p3) => p3 = M1(); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,46): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action x1 = (p1) => p1 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(12, 46), // (19,30): warning CS8600: Converting null literal or possible null value to non-nullable type. // D1 x3 = (p3) => p3 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(19, 30) ); } [Fact] public void Lambda_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } delegate CL1 D1(); delegate CL1? D2(); void M2(int x, D1 y) {} void M2(long x, D2 y) {} void M3(long x, D2 y) {} void M3(int x, D1 y) {} void Test1(int x1) { M2(x1, () => M1()); } void Test2(int x2) { M3(x2, () => M1()); } void Test3(int x3) { M2(x3, delegate { return M1(); }); } void Test4(int x4) { M3(x4, delegate { return M1(); }); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (20,22): warning CS8603: Possible null reference return. // M2(x1, () => M1()); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(20, 22), // (25,22): warning CS8603: Possible null reference return. // M3(x2, () => M1()); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(25, 22), // (30,34): warning CS8603: Possible null reference return. // M2(x3, delegate { return M1(); }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(30, 34), // (35,34): warning CS8603: Possible null reference return. // M3(x4, delegate { return M1(); }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(35, 34) ); } [Fact] public void Lambda_06() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } delegate CL1 D1(); delegate CL1? D2(); void M2(int x, D2 y) {} void M2(long x, D1 y) {} void M3(long x, D1 y) {} void M3(int x, D2 y) {} void Test1(int x1) { M2(x1, () => M1()); } void Test2(int x2) { M3(x2, () => M1()); } void Test3(int x3) { M2(x3, delegate { return M1(); }); } void Test4(int x4) { M3(x4, delegate { return M1(); }); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Lambda_07() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } delegate T D(); void M2(int x, D y) {} void M2(int x, D y) {} void M3(int x, D y) {} void M3(int x, D y) {} void Test1(int x1) { M2(x1, () => M1()); } void Test2(int x2) { M3(x2, () => M1()); } void Test3(int x3) { M2(x3, delegate { return M1(); }); } void Test4(int x4) { M3(x4, delegate { return M1(); }); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (19,22): warning CS8603: Possible null reference return. // M2(x1, () => M1()); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(19, 22), // (24,22): warning CS8603: Possible null reference return. // M3(x2, () => M1()); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(24, 22), // (29,34): warning CS8603: Possible null reference return. // M2(x3, delegate { return M1(); }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(29, 34), // (34,34): warning CS8603: Possible null reference return. // M3(x4, delegate { return M1(); }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "M1()").WithLocation(34, 34) ); } [Fact] public void Lambda_08() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } delegate T D(); void M2(int x, D y) {} void M2(int x, D y) {} void M3(int x, D y) {} void M3(int x, D y) {} void Test1(int x1) { M2(x1, () => M1()); } void Test2(int x2) { M3(x2, () => M1()); } void Test3(int x3) { M2(x3, delegate { return M1(); }); } void Test4(int x4) { M3(x4, delegate { return M1(); }); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Lambda_09() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } delegate T1 D(T2 y); void M2(int x, D y) {} void M2(int x, D y) {} void M3(int x, D y) {} void M3(int x, D y) {} void Test1(int x1) { M2(x1, (y1) => { y1 = M1(); return y1; }); } void Test2(int x2) { M3(x2, (y2) => { y2 = M1(); return y2; }); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (21,26): warning CS8600: Converting null literal or possible null value to non-nullable type. // y1 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(21, 26), // (22,28): warning CS8603: Possible null reference return. // return y1; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y1").WithLocation(22, 28), // (30,26): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(30, 26), // (31,28): warning CS8603: Possible null reference return. // return y2; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y2").WithLocation(31, 28) ); } [Fact] public void Lambda_10() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } delegate T1 D(T2 y); void M2(int x, D y) {} void M2(int x, D y) {} void M3(int x, D y) {} void M3(int x, D y) {} void Test1(int x1) { M2(x1, (y1) => { y1 = M1(); return y1; }); } void Test2(int x2) { M3(x2, (y2) => { y2 = M1(); return y2; }); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (22,28): warning CS8603: Possible null reference return. // return y1; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y1").WithLocation(22, 28), // (31,28): warning CS8603: Possible null reference return. // return y2; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y2").WithLocation(31, 28) ); } [Fact] public void Lambda_11() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Action x1 = (CL1 p1) => p1 = M1(); } void Test2() { System.Action x2 = delegate (CL1 p2) { p2 = M1(); }; } delegate void D1(CL1 p); void Test3() { D1 x3 = (CL1 p3) => p3 = M1(); } void Test4() { D1 x4 = delegate (CL1 p4) { p4 = M1(); }; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action x1 = (CL1 p1) => p1 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(12, 50), // (17,58): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action x2 = delegate (CL1 p2) { p2 = M1(); }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(17, 58), // (24,34): warning CS8600: Converting null literal or possible null value to non-nullable type. // D1 x3 = (CL1 p3) => p3 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(24, 34), // (29,42): warning CS8600: Converting null literal or possible null value to non-nullable type. // D1 x4 = delegate (CL1 p4) { p4 = M1(); }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(29, 42) ); } [Fact] public void Lambda_12() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Action x1 = (CL1 p1) => p1 = M1(); } void Test2() { System.Action x2 = delegate (CL1 p2) { p2 = M1(); }; } delegate void D1(CL1? p); void Test3() { D1 x3 = (CL1 p3) => p3 = M1(); } void Test4() { D1 x4 = delegate (CL1 p4) { p4 = M1(); }; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action x1 = (CL1 p1) => p1 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(12, 51), // (12,34): warning CS8622: Nullability of reference types in type of parameter 'p1' of 'lambda expression' doesn't match the target delegate 'Action'. // System.Action x1 = (CL1 p1) => p1 = M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1 p1) => p1 = M1()").WithArguments("p1", "lambda expression", "System.Action").WithLocation(12, 34), // (17,59): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action x2 = delegate (CL1 p2) { p2 = M1(); }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(17, 59), // (17,34): warning CS8622: Nullability of reference types in type of parameter 'p2' of 'anonymous method' doesn't match the target delegate 'Action'. // System.Action x2 = delegate (CL1 p2) { p2 = M1(); }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "delegate (CL1 p2) { p2 = M1(); }").WithArguments("p2", "anonymous method", "System.Action").WithLocation(17, 34), // (24,34): warning CS8600: Converting null literal or possible null value to non-nullable type. // D1 x3 = (CL1 p3) => p3 = M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(24, 34), // (24,17): warning CS8622: Nullability of reference types in type of parameter 'p3' of 'lambda expression' doesn't match the target delegate 'C.D1'. // D1 x3 = (CL1 p3) => p3 = M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1 p3) => p3 = M1()").WithArguments("p3", "lambda expression", "C.D1").WithLocation(24, 17), // (29,42): warning CS8600: Converting null literal or possible null value to non-nullable type. // D1 x4 = delegate (CL1 p4) { p4 = M1(); }; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M1()").WithLocation(29, 42), // (29,17): warning CS8622: Nullability of reference types in type of parameter 'p4' of 'anonymous method' doesn't match the target delegate 'C.D1'. // D1 x4 = delegate (CL1 p4) { p4 = M1(); }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "delegate (CL1 p4) { p4 = M1(); }").WithArguments("p4", "anonymous method", "C.D1").WithLocation(29, 17) ); } [Fact] public void Lambda_13() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Action x1 = (CL1? p1) => p1 = M1(); } void Test2() { System.Action x2 = delegate (CL1? p2) { p2 = M1(); }; } delegate void D1(CL1 p); void Test3() { D1 x3 = (CL1? p3) => p3 = M1(); } void Test4() { D1 x4 = delegate (CL1? p4) { p4 = M1(); }; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,33): warning CS8622: Nullability of reference types in type of parameter 'p1' of 'lambda expression' doesn't match the target delegate 'Action'. // System.Action x1 = (CL1? p1) => p1 = M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1? p1) => p1 = M1()").WithArguments("p1", "lambda expression", "System.Action").WithLocation(12, 33), // (17,33): warning CS8622: Nullability of reference types in type of parameter 'p2' of 'anonymous method' doesn't match the target delegate 'Action'. // System.Action x2 = delegate (CL1? p2) { p2 = M1(); }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "delegate (CL1? p2) { p2 = M1(); }").WithArguments("p2", "anonymous method", "System.Action").WithLocation(17, 33), // (24,17): warning CS8622: Nullability of reference types in type of parameter 'p3' of 'lambda expression' doesn't match the target delegate 'C.D1'. // D1 x3 = (CL1? p3) => p3 = M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1? p3) => p3 = M1()").WithArguments("p3", "lambda expression", "C.D1").WithLocation(24, 17), // (29,17): warning CS8622: Nullability of reference types in type of parameter 'p4' of 'anonymous method' doesn't match the target delegate 'C.D1'. // D1 x4 = delegate (CL1? p4) { p4 = M1(); }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "delegate (CL1? p4) { p4 = M1(); }").WithArguments("p4", "anonymous method", "C.D1").WithLocation(29, 17) ); } [Fact] public void Lambda_14() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL1? M1() { return null; } void Test1() { System.Action x1 = (CL1? p1) => p1 = M1(); } void Test2() { System.Action x2 = delegate (CL1? p2) { p2 = M1(); }; } delegate void D1(CL1? p); void Test3() { D1 x3 = (CL1? p3) => p3 = M1(); } void Test4() { D1 x4 = delegate (CL1? p4) { p4 = M1(); }; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Lambda_15() { CSharpCompilation notAnnotated = CreateCompilation(@" public class CL0 { public static void M1(System.Func, CL0> x) {} } public class CL1 { public T F1; public CL1() { F1 = default(T); } } ", options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} static void Test1() { CL0.M1(p1 => { p1.F1 = null; p1 = null; return null; }); } static void Test2() { System.Func, CL0> l2 = p2 => { p2.F1 = null; // 1 p2 = null; // 2 return null; // 3 }; } } " }, options: WithNonNullTypesTrue(), references: new[] { notAnnotated.EmitToImageReference() }); c.VerifyDiagnostics( // (20,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // p2.F1 = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(20, 29), // (21,26): warning CS8600: Converting null literal or possible null value to non-nullable type. // p2 = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(21, 26), // (22,28): warning CS8603: Possible null reference return. // return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(22, 28) ); } [Fact] public void Lambda_16() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1() { System.Action> x1 = (CL1 p1) => System.Console.WriteLine(); } void Test2() { System.Action> x2 = (CL1 p2) => System.Console.WriteLine(); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,42): warning CS8622: Nullability of reference types in type of parameter 'p1' of 'lambda expression' doesn't match the target delegate 'Action>'. // System.Action> x1 = (CL1 p1) => System.Console.WriteLine(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1 p1) => System.Console.WriteLine()").WithArguments("p1", "lambda expression", "System.Action>").WithLocation(10, 42), // (15,41): warning CS8622: Nullability of reference types in type of parameter 'p2' of 'lambda expression' doesn't match the target delegate 'Action>'. // System.Action> x2 = (CL1 p2) => System.Console.WriteLine(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1 p2) => System.Console.WriteLine()").WithArguments("p2", "lambda expression", "System.Action>").WithLocation(15, 41) ); } [Fact] public void Lambda_17() { CSharpCompilation c = CreateCompilation(new[] { @" using System.Linq.Expressions; class C { static void Main() { } void Test1() { Expression>> x1 = (CL1 p1) => System.Console.WriteLine(); } void Test2() { Expression>> x2 = (CL1 p2) => System.Console.WriteLine(); } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,54): warning CS8622: Nullability of reference types in type of parameter 'p1' of 'lambda expression' doesn't match the target delegate 'Action>'. // Expression>> x1 = (CL1 p1) => System.Console.WriteLine(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1 p1) => System.Console.WriteLine()").WithArguments("p1", "lambda expression", "System.Action>").WithLocation(12, 54), // (17,53): warning CS8622: Nullability of reference types in type of parameter 'p2' of 'lambda expression' doesn't match the target delegate 'Action>'. // Expression>> x2 = (CL1 p2) => System.Console.WriteLine(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(CL1 p2) => System.Console.WriteLine()").WithArguments("p2", "lambda expression", "System.Action>").WithLocation(17, 53) ); } [Fact] public void Lambda_18() { var source = @"delegate T D(T t) where T : class; class C { static void F() { var d1 = (D)((string s1) => { s1 = null; return s1; }); var d2 = (D)((string? s2) => { s2.ToString(); return s2; }); // suppressed var d3 = (D)((string s1) => { s1 = null; return s1; }!); var d4 = (D)((string? s2) => { s2.ToString(); return s2; }!); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): warning CS8622: Nullability of reference types in type of parameter 's1' of 'lambda expression' doesn't match the target delegate 'D'. // var d1 = (D)((string s1) => { s1 = null; return s1; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(D)((string s1) => { s1 = null; return s1; })").WithArguments("s1", "lambda expression", "D").WithLocation(6, 18), // (6,21): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'D'. Nullability of type argument 'string?' doesn't match 'class' constraint. // var d1 = (D)((string s1) => { s1 = null; return s1; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("D", "T", "string?").WithLocation(6, 21), // (6,53): warning CS8600: Converting null literal or possible null value to non-nullable type. // var d1 = (D)((string s1) => { s1 = null; return s1; }); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 53), // (7,18): warning CS8622: Nullability of reference types in type of parameter 's2' of 'lambda expression' doesn't match the target delegate 'D'. // var d2 = (D)((string? s2) => { s2.ToString(); return s2; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(D)((string? s2) => { s2.ToString(); return s2; })").WithArguments("s2", "lambda expression", "D").WithLocation(7, 18), // (7,48): warning CS8602: Dereference of a possibly null reference. // var d2 = (D)((string? s2) => { s2.ToString(); return s2; }); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(7, 48), // (10,21): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'D'. Nullability of type argument 'string?' doesn't match 'class' constraint. // var d3 = (D)((string s1) => { s1 = null; return s1; }!); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("D", "T", "string?").WithLocation(10, 21), // (10,53): warning CS8600: Converting null literal or possible null value to non-nullable type. // var d3 = (D)((string s1) => { s1 = null; return s1; }!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 53), // (11,48): warning CS8602: Dereference of a possibly null reference. // var d4 = (D)((string? s2) => { s2.ToString(); return s2; }!); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(11, 48) ); } /// /// To track nullability of captured variables inside and outside a lambda, /// the lambda should be considered executed at the location the lambda /// is converted to a delegate. /// [Fact] [WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void Lambda_19() { var source = @"using System; class C { static void F1(object? x1, object y1) { object z1 = y1; Action f = () => { z1 = x1; // warning }; f(); z1.ToString(); } static void F2(object? x2, object y2) { object z2 = x2; // warning Action f = () => { z2 = y2; }; f(); z2.ToString(); // warning } static void F3(object? x3, object y3) { object z3 = y3; if (x3 == null) return; Action f = () => { z3 = x3; }; f(); z3.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z1 = x1; // warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(9, 18), // (16,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object z2 = x2; // warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(16, 21), // (22,9): warning CS8602: Dereference of a possibly null reference. // z2.ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(22, 9)); } [Fact] public void LambdaReturnValue_01() { var source = @"using System; class C { static void F(Func f) { } static void G(string x, object? y) { F(() => { if ((object)x == y) return x; return y; }); F(() => { if (y == null) return x; return y; }); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,56): warning CS8603: Possible null reference return. // F(() => { if ((object)x == y) return x; return y; }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y").WithLocation(9, 56)); } [Fact] public void LambdaReturnValue_02() { var source = @"using System; class C { static void F(Func f) { } static void G(bool b, object x, string? y) { F(() => { if (b) return x; return y; }); F(() => { if (b) return y; return x; }); } static void H(bool b, object? x, string y) { F(() => { if (b) return x; return y; }); F(() => { if (b) return y; return x; }); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,43): warning CS8603: Possible null reference return. // F(() => { if (b) return x; return y; }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y").WithLocation(9, 43), // (10,33): warning CS8603: Possible null reference return. // F(() => { if (b) return y; return x; }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y").WithLocation(10, 33), // (14,33): warning CS8603: Possible null reference return. // F(() => { if (b) return x; return y; }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "x").WithLocation(14, 33), // (15,43): warning CS8603: Possible null reference return. // F(() => { if (b) return y; return x; }); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "x").WithLocation(15, 43)); } [Fact] public void LambdaReturnValue_03() { var source = @"using System; class C { static T F(Func f) { throw null!; } static void G(bool b, object x, string? y) { F(() => { if (b) return x; return y; }).ToString(); } static void H(bool b, object? x, string y) { F(() => { if (b) return x; return y; }).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // F(() => { if (b) return x; return y; }).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => { if (b) return x; return y; })").WithLocation(10, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // F(() => { if (b) return x; return y; }).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => { if (b) return x; return y; })").WithLocation(14, 9)); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void LambdaReturnValue_04() { var source = @"using System; class C { static T F(Func f) { throw null!; } static void G(object? o) { F(() => o).ToString(); // 1 if (o != null) F(() => o).ToString(); F(() => { return o; }).ToString(); // 2 if (o != null) F(() => { return o; }).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // F(() => o).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => o)").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // F(() => { return o; }).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => { return o; })").WithLocation(12, 9)); } [Fact] public void LambdaReturnValue_05() { var source = @"using System; class C { static T F(Func f) { throw null!; } static void G() { F(o => { if (o == null) throw new ArgumentException(); return o; }).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void LambdaReturnValue_05_WithSuppression() { var source = @"using System; class C { static T F(Func f) { throw null!; } static void G() { F(o => { if (o == null) throw new ArgumentException(); return o; }!).ToString(); } }"; // covers suppression case in InferReturnType var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void LambdaReturnValue_06() { var source = @"using System; class C { static U F(Func f, T t) { return f(t); } static void M(object? x) { F(y => F(z => z, y), x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // F(y => F(z => z, y), x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y => F(z => z, y), x)").WithLocation(10, 9)); } [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] [WorkItem(30480, "https://github.com/dotnet/roslyn/issues/30480")] [Fact] public void LambdaReturnValue_NestedNullability_Invariant() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"using System; class C { static T F(Func f) => throw null!; static void F(B x, B y) { var z = A.F/*T:B!*/; F(i => { switch (i) { case 0: return x; default: return x; }})/*T:B!*/; F(i => { switch (i) { case 0: return x; default: return y; }})/*T:B!*/; // 1 F(i => { switch (i) { case 0: return x; default: return z; }})/*T:B!*/; F(i => { switch (i) { case 0: return y; default: return x; }})/*T:B!*/; // 2 F(i => { switch (i) { case 0: return y; default: return y; }})/*T:B!*/; F(i => { switch (i) { case 0: return y; default: return z; }})/*T:B!*/; F(i => { switch (i) { case 0: return z; default: return x; }})/*T:B!*/; F(i => { switch (i) { case 0: return z; default: return y; }})/*T:B!*/; F(i => { switch (i) { case 0: return z; default: return z; }})/*T:B!*/; F(i => { switch (i) { case 0: return x; case 1: return y; default: return z; }})/*T:B!*/; // 3 F(i => { switch (i) { case 0: return z; case 1: return y; default: return x; }})/*T:B!*/; // 4 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (9,46): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // F(i => { switch (i) { case 0: return x; default: return y; }})/*T:B!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 46), // (11,65): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // F(i => { switch (i) { case 0: return y; default: return x; }})/*T:B!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(11, 65), // (17,46): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // F(i => { switch (i) { case 0: return x; case 1: return y; default: return z; }})/*T:B*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(17, 46), // (18,83): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // F(i => { switch (i) { case 0: return z; case 1: return y; default: return x; }})/*T:B*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(18, 83) ); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void LambdaReturnValue_NestedNullability_Variant_01() { var source0 = @"public class A { public static I F; public static IIn FIn; public static IOut FOut; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"using System; class C { static T F(Func f) => throw null!; static void F1(I x, I y) { var z = A.F/*T:I!*/; F(b => { if (b) return x; else return x; })/*T:I!*/; F(b => { if (b) return x; else return y; })/*T:I!*/; // 1 F(b => { if (b) return x; else return z; })/*T:I!*/; F(b => { if (b) return y; else return x; })/*T:I!*/; // 2 F(b => { if (b) return y; else return y; })/*T:I!*/; F(b => { if (b) return y; else return z; })/*T:I!*/; F(b => { if (b) return z; else return x; })/*T:I!*/; F(b => { if (b) return z; else return y; })/*T:I!*/; F(b => { if (b) return z; else return z; })/*T:I!*/; } static void F2(IIn x, IIn y) { var z = A.FIn/*T:IIn!*/; F(b => { if (b) return x; else return x; })/*T:IIn!*/; F(b => { if (b) return x; else return y; })/*T:IIn!*/; F(b => { if (b) return x; else return z; })/*T:IIn!*/; F(b => { if (b) return y; else return x; })/*T:IIn!*/; F(b => { if (b) return y; else return y; })/*T:IIn!*/; F(b => { if (b) return y; else return z; })/*T:IIn!*/; F(b => { if (b) return z; else return x; })/*T:IIn!*/; F(b => { if (b) return z; else return y; })/*T:IIn!*/; F(b => { if (b) return z; else return z; })/*T:IIn!*/; } static void F3(IOut x, IOut y) { var z = A.FOut/*T:IOut!*/; F(b => { if (b) return x; else return x; })/*T:IOut!*/; F(b => { if (b) return x; else return y; })/*T:IOut!*/; F(b => { if (b) return x; else return z; })/*T:IOut!*/; F(b => { if (b) return y; else return x; })/*T:IOut!*/; F(b => { if (b) return y; else return y; })/*T:IOut!*/; F(b => { if (b) return y; else return z; })/*T:IOut!*/; F(b => { if (b) return z; else return x; })/*T:IOut!*/; F(b => { if (b) return z; else return y; })/*T:IOut!*/; F(b => { if (b) return z; else return z; })/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (9,47): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // F(b => { if (b) return x; else return y; })/*T:I!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(9, 47), // (11,32): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // F(b => { if (b) return y; else return x; })/*T:I!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(11, 32) ); } [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] [Fact] public void LambdaReturnValue_NestedNullability_Variant_02() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"using System; class C { static Func CreateFunc(T t) => throw null!; static void F(B x, B y) { var f = CreateFunc(y)/*Func!>!*/; var z = A.F/*T:B!*/; f = i => { switch (i) { case 0: return x; default: return x; }}; // 1 2 f = i => { switch (i) { case 0: return x; default: return y; }}; // 3 f = i => { switch (i) { case 0: return x; default: return z; }}; // 4 f = i => { switch (i) { case 0: return y; default: return x; }}; // 5 f = i => { switch (i) { case 0: return y; default: return y; }}; f = i => { switch (i) { case 0: return y; default: return z; }}; f = i => { switch (i) { case 0: return z; default: return x; }}; // 6 f = i => { switch (i) { case 0: return z; default: return y; }}; f = i => { switch (i) { case 0: return z; default: return z; }}; f = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; // 7 f = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; // 8 var g = CreateFunc(z)/*Func!>!*/; g = i => { switch (i) { case 0: return x; default: return x; }}; g = i => { switch (i) { case 0: return x; default: return y; }}; g = i => { switch (i) { case 0: return x; default: return z; }}; g = i => { switch (i) { case 0: return y; default: return x; }}; g = i => { switch (i) { case 0: return y; default: return y; }}; g = i => { switch (i) { case 0: return y; default: return z; }}; g = i => { switch (i) { case 0: return z; default: return x; }}; g = i => { switch (i) { case 0: return z; default: return y; }}; g = i => { switch (i) { case 0: return z; default: return z; }}; g = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; g = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (9,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return x; default: return x; }}; // 1 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 48), // (9,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return x; default: return x; }}; // 1 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(9, 67), // (10,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return x; default: return y; }}; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(10, 48), // (11,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return x; default: return z; }}; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(11, 48), // (12,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return y; default: return x; }}; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(12, 67), // (15,67): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return z; default: return x; }}; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(15, 67), // (18,48): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return x; case 1: return y; default: return z; }}; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(18, 48), // (19,85): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // f = i => { switch (i) { case 0: return z; case 1: return y; default: return x; }}; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "B").WithLocation(19, 85) ); comp.VerifyTypes(); } [WorkItem(30432, "https://github.com/dotnet/roslyn/issues/30432")] [Fact] public void LambdaReturnValue_TopLevelNullability_Ref() { var source = @"delegate ref V D(ref T t, ref U u); class C { static V F(D d) => throw null!; static void G(bool b) { F((ref object? x1, ref object? y1) => { if (b) return ref x1; return ref y1; }); F((ref object? x2, ref object y2) => { if (b) return ref x2; return ref y2; }); F((ref object x3, ref object? y3) => { if (b) return ref x3; return ref y3; }); F((ref object x4, ref object y4) => { if (b) return ref x4; return ref y4; }); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,81): warning CS8619: Nullability of reference types in value of type 'object' doesn't match target type 'object?'. // F((ref object? x2, ref object y2) => { if (b) return ref x2; return ref y2; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y2").WithArguments("object", "object?").WithLocation(8, 81), // (9,66): warning CS8619: Nullability of reference types in value of type 'object' doesn't match target type 'object?'. // F((ref object x3, ref object? y3) => { if (b) return ref x3; return ref y3; }); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("object", "object?").WithLocation(9, 66) ); } [WorkItem(30432, "https://github.com/dotnet/roslyn/issues/30432")] [WorkItem(30964, "https://github.com/dotnet/roslyn/issues/30964")] [Fact] public void LambdaReturnValue_NestedNullability_Ref() { var source = @"delegate ref V D(ref T t, ref U u); interface I { } interface IIn { } interface IOut { } class C { static V F(D d) => throw null!; static void G(bool b) { // I F((ref I a1, ref I b1) => { if (b) return ref a1; return ref b1; }); F((ref I a2, ref I b2) => { if (b) return ref a2; return ref b2; }); // 1 F((ref I a3, ref I b3) => { if (b) return ref a3; return ref b3; }); // 2 F((ref I a4, ref I b4) => { if (b) return ref a4; return ref b4; }); // IIn F((ref IIn c1, ref IIn d1) => { if (b) return ref c1; return ref d1; }); F((ref IIn c2, ref IIn d2) => { if (b) return ref c2; return ref d2; }); // 3 F((ref IIn c3, ref IIn d3) => { if (b) return ref c3; return ref d3; }); // 4 F((ref IIn c4, ref IIn d4) => { if (b) return ref c4; return ref d4; }); // IOut F((ref IOut e1, ref IOut f1) => { if (b) return ref e1; return ref f1; }); F((ref IOut e2, ref IOut f2) => { if (b) return ref e2; return ref f2; }); // 5 F((ref IOut e3, ref IOut f3) => { if (b) return ref e3; return ref f3; }); // 6 F((ref IOut e4, ref IOut f4) => { if (b) return ref e4; return ref f4; }); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,72): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // F((ref I a2, ref I b2) => { if (b) return ref a2; return ref b2; }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("I", "I").WithLocation(12, 72), // (13,87): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // F((ref I a3, ref I b3) => { if (b) return ref a3; return ref b3; }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b3").WithArguments("I", "I").WithLocation(13, 87), // (17,76): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // F((ref IIn c2, ref IIn d2) => { if (b) return ref c2; return ref d2; }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c2").WithArguments("IIn", "IIn").WithLocation(17, 76), // (18,91): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // F((ref IIn c3, ref IIn d3) => { if (b) return ref c3; return ref d3; }); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "d3").WithArguments("IIn", "IIn").WithLocation(18, 91), // (22,93): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // F((ref IOut e2, ref IOut f2) => { if (b) return ref e2; return ref f2; }); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "f2").WithArguments("IOut", "IOut").WithLocation(22, 93), // (23,78): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // F((ref IOut e3, ref IOut f3) => { if (b) return ref e3; return ref f3; }); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "e3").WithArguments("IOut", "IOut").WithLocation(23, 78) ); } [Fact] public void LambdaParameterValue() { var source = @"using System; class C { static void F(T t, Action f) { } static void G(object? x) { F(x, y => F(y, z => { y.ToString(); z.ToString(); })); if (x != null) F(x, y => F(y, z => { y.ToString(); z.ToString(); })); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,31): warning CS8602: Dereference of a possibly null reference. // F(x, y => F(y, z => { y.ToString(); z.ToString(); })); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 31), // (9,45): warning CS8602: Dereference of a possibly null reference. // F(x, y => F(y, z => { y.ToString(); z.ToString(); })); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(9, 45)); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33645")] [WorkItem(33645, "https://github.com/dotnet/roslyn/issues/33645")] public void ReinferLambdaReturnType() { var source = @"using System; class C { static T F(Func f) => f(); static void G(object? x) { F(() => x)/*T:object?*/; if (x == null) return; F(() => x)/*T:object!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] [WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void IdentityConversion_LambdaReturnType() { var source = @"delegate T D(); interface I { } class C { static void F(object x, object? y) { D a = () => x; D b = () => y; // 1 if (y == null) return; a = () => y; b = () => y; a = (D)(() => y); b = (D)(() => y); } static void F(I x, I y) { D> a = () => x; // 2 D> b = () => y; // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,29): warning CS8603: Possible null reference return. // D b = () => y; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y").WithLocation(8, 29), // (17,33): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // D> a = () => x; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("I", "I").WithLocation(17, 33), // (18,32): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // D> b = () => y; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(18, 32)); } [Fact] public void IdentityConversion_LambdaParameter() { var source = @"delegate void D(T t); interface I { } class C { static void F() { D a = (object o) => { }; D b = (object? o) => { }; D> c = (I o) => { }; D> d = (I o) => { }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,24): warning CS8622: Nullability of reference types in type of parameter 'o' of 'lambda expression' doesn't match the target delegate 'D'. // D a = (object o) => { }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(object o) => { }").WithArguments("o", "lambda expression", "D").WithLocation(7, 24), // (8,23): warning CS8622: Nullability of reference types in type of parameter 'o' of 'lambda expression' doesn't match the target delegate 'D'. // D b = (object? o) => { }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(object? o) => { }").WithArguments("o", "lambda expression", "D").WithLocation(8, 23), // (9,27): warning CS8622: Nullability of reference types in type of parameter 'o' of 'lambda expression' doesn't match the target delegate 'D>'. // D> c = (I o) => { }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(I o) => { }").WithArguments("o", "lambda expression", "D>").WithLocation(9, 27), // (10,26): warning CS8622: Nullability of reference types in type of parameter 'o' of 'lambda expression' doesn't match the target delegate 'D>'. // D> d = (I o) => { }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(I o) => { }").WithArguments("o", "lambda expression", "D>").WithLocation(10, 26)); } [Fact] [WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void ReturnTypeInference_01() { var source = @"class C { static T F(System.Func f) { return f(); } static void G(string x, string? y) { F(() => x).ToString(); F(() => y).ToString(); // 1 if (y != null) F(() => y).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // F(() => y).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => y)").WithLocation(10, 9)); } [Fact] public void ReturnTypeInference_DelegateTypes() { var source = @" class C { System.Func D1(T t) => k => t; void M1(bool b, string? s, string s2) { M2(k => s, D1(s)) /*T:System.Func!*/; M2(D1(s), k => s) /*T:System.Func!*/; M2(k => s2, D1(s2)) /*T:System.Func!*/; M2(D1(s2), k => s2) /*T:System.Func!*/; _ = (new[] { k => s, D1(s) }) /*T:System.Func![]!*/; _ = (new[] { D1(s), k => s }) /*T:System.Func![]!*/; _ = (new[] { k => s2, D1(s2) }) /*T:System.Func![]!*/; // wrong _ = (new[] { D1(s2), k => s2 }) /*T:System.Func![]!*/; // wrong } T M2(T x, T y) => throw null!; }"; // See https://github.com/dotnet/roslyn/issues/34392 // Best type inference involving lambda conversion should agree with method type inference var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } // Multiple returns, one of which is null. [Fact] public void ReturnTypeInference_02() { var source = @"class C { static T F(System.Func f) { return f(); } static void G(string x) { F(() => { if (x.Length > 0) return x; return null; }).ToString(); F(() => { if (x.Length == 0) return null; return x; }).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // F(() => { if (x.Length > 0) return x; return null; }).ToString(); 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_NullReferenceReceiver, "F(() => { if (x.Length == 0) return null; return x; })").WithLocation(10, 9)); } [Fact] public void ReturnTypeInference_CSharp7() { var source = @"using System; class C { static void Main(string[] args) { args.F(arg => arg.Length); } } static class E { internal static U[] F(this T[] a, Func f) => throw new Exception(); }"; var comp = CreateCompilationWithMscorlib45( new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); } [Fact] public void UnboundLambda_01() { var source = @"class C { static void F() { var y = x => x; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,13): error CS0815: Cannot assign lambda expression to an implicitly-typed variable // var y = x => x; Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableAssignedBadValue, "y = x => x").WithArguments("lambda expression").WithLocation(5, 13)); } [Fact] public void UnboundLambda_02() { var source = @"class C { static void F(object? x) { var z = y => y ?? x.ToString(); System.Func z2 = y => y ?? x.ToString(); System.Func z3 = y => null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,13): error CS0815: Cannot assign lambda expression to an implicitly-typed variable // var z = y => y ?? x.ToString(); Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableAssignedBadValue, "z = y => y ?? x.ToString()").WithArguments("lambda expression").WithLocation(5, 13), // (5,27): warning CS8602: Dereference of a possibly null reference. // var z = y => y ?? x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(5, 27), // (6,53): warning CS8602: Dereference of a possibly null reference. // System.Func z2 = y => y ?? x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 53), // (7,48): warning CS8603: Possible null reference return. // System.Func z3 = y => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(7, 48)); } /// /// Inferred nullability of captured variables should be tracked across /// local function invocations, as if the local function was inlined. /// [Fact] [WorkItem(29892, "https://github.com/dotnet/roslyn/issues/29892")] public void LocalFunction_01() { var source = @"class C { static void F1(object? x1, object y1) { object z1 = y1; f(); z1.ToString(); // warning void f() { z1 = x1; // warning } } static void F2(object? x2, object y2) { object z2 = x2; // warning f(); z2.ToString(); void f() { z2 = y2; } } static void F3(object? x3, object y3) { object z3 = y3; void f() { z3 = x3; } if (x3 == null) return; f(); z3.ToString(); } static void F4(object? x4) { f().ToString(); // warning if (x4 != null) f().ToString(); object? f() => x4; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29892: Should report warnings as indicated in source above. comp.VerifyDiagnostics( // (10,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z1 = x1; // warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(10, 18), // (15,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object z2 = x2; // warning Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(15, 21), // (17,9): warning CS8602: Dereference of a possibly null reference. // z2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(17, 9), // (28,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // z3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(28, 18), // (36,9): warning CS8602: Dereference of a possibly null reference. // f().ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "f()").WithLocation(36, 9), // (37,25): warning CS8602: Dereference of a possibly null reference. // if (x4 != null) f().ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "f()").WithLocation(37, 25)); } /// /// Should report warnings within unused local functions. /// [Fact] [WorkItem(29892, "https://github.com/dotnet/roslyn/issues/29892")] public void LocalFunction_NoCallers() { var source = @"#pragma warning disable 8321 class C { static void F1(object? x1) { void f1() { x1.ToString(); // 1 } } static void F2(object? x2) { if (x2 == null) return; void f2() { x2.ToString(); // 2 } } static void F3(object? x3) { object? y3 = x3; void f3() { y3.ToString(); // 3 } if (y3 == null) return; void g3() { y3.ToString(); // 4 } } static void F4() { void f4(object? x4) { x4.ToString(); // 5 } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29892: Should report warnings for `y3.ToString()`. comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(8, 13), // (16,13): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(16, 13), // (36,13): warning CS8602: Dereference of a possibly null reference. // x4.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4").WithLocation(36, 13)); } [Fact] public void New_01() { var source = @"class C { static void F1() { object? x1; x1 = new object?(); // error 1 x1 = new object? { }; // error 2 x1 = (new object?[1])[0]; x1 = new object[]? {}; // error 3 } static void F2() { object? x2; x2 = new T2?(); // error 4 x2 = new T2? { }; // error 5 x2 = (new T2?[1])[0]; } static void F3() where T3 : class, new() { object? x3; x3 = new T3?(); // error 6 x3 = new T3? { }; // error 7 x3 = (new T3?[1])[0]; } static void F4() where T4 : new() { object? x4; x4 = new T4?(); // error 8 x4 = new T4? { }; // error 9 x4 = (new T4?[1])[0]; x4 = new System.Nullable? { }; // error 11 } static void F5() where T5 : class { object? x5; x5 = new T5?(); // error 10 x5 = new T5? { }; // error 11 x5 = (new T5?[1])[0]; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,14): error CS8628: Cannot use a nullable reference type in object creation. // x1 = new object?(); // error 1 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new object?()").WithArguments("object").WithLocation(6, 14), // (7,14): error CS8628: Cannot use a nullable reference type in object creation. // x1 = new object? { }; // error 2 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new object? { }").WithArguments("object").WithLocation(7, 14), // (9,14): error CS8628: Cannot use a nullable reference type in object creation. // x1 = new object[]? {}; // error 3 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new object[]? {}").WithArguments("object[]").WithLocation(9, 14), // (9,18): error CS8386: Invalid object creation // x1 = new object[]? {}; // error 3 Diagnostic(ErrorCode.ERR_InvalidObjectCreation, "object[]?").WithArguments("object[]").WithLocation(9, 18), // (14,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x2 = new T2?(); // error 4 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(14, 18), // (14,14): error CS8628: Cannot use a nullable reference type in object creation. // x2 = new T2?(); // error 4 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T2?()").WithArguments("T2").WithLocation(14, 14), // (14,14): error CS0304: Cannot create an instance of the variable type 'T2' because it does not have the new() constraint // x2 = new T2?(); // error 4 Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T2?()").WithArguments("T2").WithLocation(14, 14), // (15,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x2 = new T2? { }; // error 5 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(15, 18), // (15,14): error CS8628: Cannot use a nullable reference type in object creation. // x2 = new T2? { }; // error 5 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T2? { }").WithArguments("T2").WithLocation(15, 14), // (15,14): error CS0304: Cannot create an instance of the variable type 'T2' because it does not have the new() constraint // x2 = new T2? { }; // error 5 Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T2? { }").WithArguments("T2").WithLocation(15, 14), // (16,19): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x2 = (new T2?[1])[0]; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(16, 19), // (21,14): error CS8628: Cannot use a nullable reference type in object creation. // x3 = new T3?(); // error 6 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T3?()").WithArguments("T3").WithLocation(21, 14), // (22,14): error CS8628: Cannot use a nullable reference type in object creation. // x3 = new T3? { }; // error 7 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T3? { }").WithArguments("T3").WithLocation(22, 14), // (28,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x4 = new T4?(); // error 8 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(28, 18), // (28,14): error CS8628: Cannot use a nullable reference type in object creation. // x4 = new T4?(); // error 8 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T4?()").WithArguments("T4").WithLocation(28, 14), // (29,18): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x4 = new T4? { }; // error 9 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(29, 18), // (29,14): error CS8628: Cannot use a nullable reference type in object creation. // x4 = new T4? { }; // error 9 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T4? { }").WithArguments("T4").WithLocation(29, 14), // (30,19): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // x4 = (new T4?[1])[0]; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(30, 19), // (31,18): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // x4 = new System.Nullable? { }; // error 11 Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "System.Nullable?").WithArguments("System.Nullable", "T", "int?").WithLocation(31, 18), // (36,14): error CS8628: Cannot use a nullable reference type in object creation. // x5 = new T5?(); // error 10 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T5?()").WithArguments("T5").WithLocation(36, 14), // (36,14): error CS0304: Cannot create an instance of the variable type 'T5' because it does not have the new() constraint // x5 = new T5?(); // error 10 Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T5?()").WithArguments("T5").WithLocation(36, 14), // (37,14): error CS8628: Cannot use a nullable reference type in object creation. // x5 = new T5? { }; // error 11 Diagnostic(ErrorCode.ERR_AnnotationDisallowedInObjectCreation, "new T5? { }").WithArguments("T5").WithLocation(37, 14), // (37,14): error CS0304: Cannot create an instance of the variable type 'T5' because it does not have the new() constraint // x5 = new T5? { }; // error 11 Diagnostic(ErrorCode.ERR_NoNewTyvar, "new T5? { }").WithArguments("T5").WithLocation(37, 14) ); } [Fact] public void New_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(T1 x1) where T1 : class, new() { x1 = new T1(); } void Test2(T2 x2) where T2 : class, new() { x2 = new T2() ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } // `where T : new()` does not imply T is non-nullable. [Fact] public void New_03() { var source = @"class C { static void F1() where T : new() { } static void F2(T t) where T : new() { } static void G() where U : class, new() { object? x = null; F1(); F2(x); U? y = null; F1(); F2(y); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void New_04() { var source = @"class C { internal object? F; internal object P { get; set; } = null!; } class Program { static void F() where T : C, new() { T x = new T() { F = 1, P = null }; // 1 x.F.ToString(); x.P.ToString(); // 2 C y = new T() { F = 2, P = null }; // 3 y.F.ToString(); y.P.ToString(); // 4 C z = (C)new T() { F = 3, P = null }; // 5 z.F.ToString(); z.P.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // T x = new T() { F = 1, P = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 36), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.P").WithLocation(12, 9), // (13,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // C y = new T() { F = 2, P = null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 36), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.P.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.P").WithLocation(15, 9), // (16,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // C z = (C)new T() { F = 3, P = null }; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 39), // (18,9): warning CS8602: Dereference of a possibly null reference. // z.P.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.P").WithLocation(18, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void New_05() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F() where T : I, new() { T x = new T() { P = 1, Q = null }; // 1 x.P.ToString(); x.Q.ToString(); // 2 I y = new T() { P = 2, Q = null }; // 3 y.P.ToString(); y.Q.ToString(); // 4 I z = (I)new T() { P = 3, Q = null }; // 5 z.P.ToString(); z.Q.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // T x = new T() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 36), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Q").WithLocation(12, 9), // (13,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // I y = new T() { P = 2, Q = null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 36), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.Q.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Q").WithLocation(15, 9), // (16,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // I z = (I)new T() { P = 3, Q = null }; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 39), // (18,9): warning CS8602: Dereference of a possibly null reference. // z.Q.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Q").WithLocation(18, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void New_06() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F() where T : class, I, new() { T x = new T() { P = 1, Q = null }; // 1 x.P.ToString(); x.Q.ToString(); // 2 I y = new T() { P = 2, Q = null }; // 3 y.P.ToString(); y.Q.ToString(); // 4 I z = (I)new T() { P = 3, Q = null }; // 5 z.P.ToString(); z.Q.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // T x = new T() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 36), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Q").WithLocation(12, 9), // (13,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // I y = new T() { P = 2, Q = null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 36), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.Q.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Q").WithLocation(15, 9), // (16,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // I z = (I)new T() { P = 3, Q = null }; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 39), // (18,9): warning CS8602: Dereference of a possibly null reference. // z.Q.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Q").WithLocation(18, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void New_07() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F() where T : struct, I { T x = new T() { P = 1, Q = null }; // 1 x.P.ToString(); x.Q.ToString(); // 2 I y = new T() { P = 2, Q = null }; // 3 y.P.ToString(); y.Q.ToString(); // 4 I z = (I)new T() { P = 3, Q = null }; // 5 z.P.ToString(); z.Q.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // T x = new T() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 36), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Q").WithLocation(12, 9), // (13,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // I y = new T() { P = 2, Q = null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 36), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.Q.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Q").WithLocation(15, 9), // (16,39): warning CS8625: Cannot convert null literal to non-nullable reference type. // I z = (I)new T() { P = 3, Q = null }; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 39), // (18,9): warning CS8602: Dereference of a possibly null reference. // z.Q.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Q").WithLocation(18, 9)); } [Fact] public void DynamicObjectCreation_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = new CL0((dynamic)0); } void Test2(CL0 x2) { x2 = new CL0((dynamic)0) ?? x2; } } class CL0 { public CL0(int x) {} public CL0(long x) {} } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicObjectCreation_02() { var source = @"class C { C(object x, object y) { } static void G(object? x, dynamic y) { var o = new C(x, y); if (x != null) o = new C(y, x); } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29893: We should be able to report warnings // when all applicable methods agree on the nullability of particular parameters. // (For instance, x in F(x, y) above.) comp.VerifyDiagnostics(); } [Fact] public void DynamicObjectCreation_03() { var source = @"class C { C(object f) { F = f; } object? F; object? G; static void M(dynamic d) { var o = new C(d) { G = new object() }; o.G.ToString(); } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void DynamicIndexerAccess_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1[(dynamic)0]; } void Test2(CL0 x2) { x2 = x2[(dynamic)0] ?? x2; } } class CL0 { public CL0 this[int x] { get { return new CL0(); } set { } } public CL0 this[long x] { get { return new CL0(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicIndexerAccess_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { dynamic y1 = x1[(dynamic)0]; } void Test2(CL0 x2) { dynamic y2 = x2[(dynamic)0] ?? x2; } } class CL0 { public CL0? this[int x] { get { return new CL0(); } set { } } public CL0 this[long x] { get { return new CL0(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicIndexerAccess_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { dynamic y1 = x1[(dynamic)0]; } void Test2(CL0 x2) { dynamic y2 = x2[(dynamic)0] ?? x2; } } class CL0 { public CL0 this[int x] { get { return new CL0(); } set { } } public CL0? this[long x] { get { return new CL0(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicIndexerAccess_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { dynamic y1 = x1[(dynamic)0]; } void Test2(CL0 x2) { dynamic y2 = x2[(dynamic)0] ?? x2; } } class CL0 { public CL0? this[int x] { get { return new CL0(); } set { } } public CL0? this[long x] { get { return new CL0(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicIndexerAccess_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1[(dynamic)0]; } void Test2(CL0 x2) { x2 = x2[(dynamic)0] ?? x2; } } class CL0 { public int this[int x] { get { return x; } set { } } public int this[long x] { get { return (int)x; } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicIndexerAccess_06() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1[(dynamic)0]; } void Test2(CL0 x2) { x2 = x2[(dynamic)0] ?? x2; } } class CL0 { public int this[int x] { get { return x; } set { } } public long this[long x] { get { return x; } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicIndexerAccess_07() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(dynamic x1) { x1 = x1[0]; } void Test2(dynamic x2) { x2 = x2[0] ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicIndexerAccess_08() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1[(dynamic)0]; } void Test2(CL0 x2) { x2 = x2[(dynamic)0] ?? x2; } } class CL0 { public T this[int x] { get { return default(T); } set { } } public long this[long x] { get { return x; } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (22,22): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // get { return default(T); } Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(22, 22) ); } [Fact] public void DynamicIndexerAccess_09() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1, dynamic y1) { x1[(dynamic)0] = y1; } void Test2(CL0 x2, dynamic? y2, CL1 z2) { x2[(dynamic)0] = y2; z2[0] = y2; } } class CL0 { public CL0 this[int x] { get { return new CL0(); } set { } } public CL0 this[long x] { get { return new CL0(); } set { } } } class CL1 { public dynamic this[int x] { get { return new CL0(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,17): warning CS8601: Possible null reference assignment. // z2[0] = y2; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y2").WithLocation(15, 17) ); } [Fact] public void DynamicIndexerAccess_10() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0? x1) { x1 = x1[(dynamic)0]; } void Test2(CL0? x2) { x2 = x2[0]; } } class CL0 { public CL0 this[int x] { get { return new CL0(); } set { } } public CL0 this[long x] { get { return new CL0(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,14): warning CS8602: Dereference of a possibly null reference. // x1 = x1[(dynamic)0]; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(9, 14), // (14,14): warning CS8602: Dereference of a possibly null reference. // x2 = x2[0]; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(14, 14) ); } [Fact] public void DynamicInvocation_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { x2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public CL0 M1(int x) { return new CL0(); } public CL0 M1(long x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicInvocation_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { dynamic y1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { dynamic y2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public CL0? M1(int x) { return new CL0(); } public CL0 M1(long x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicInvocation_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { dynamic y1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { dynamic y2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public CL0 M1(int x) { return new CL0(); } public CL0? M1(long x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicInvocation_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { dynamic y1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { dynamic y2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public CL0? M1(int x) { return new CL0(); } public CL0? M1(long x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(); } [Fact] public void DynamicInvocation_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { x2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public int M1(int x) { return x; } public int M1(long x) { return (int)x; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicInvocation_06() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { x2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public int M1(int x) { return x; } public long M1(long x) { return x; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicInvocation_07() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(dynamic x1) { x1 = x1.M1(0); } void Test2(dynamic x2) { x2 = x2.M1(0) ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicInvocation_08() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0 x1) { x1 = x1.M1((dynamic)0); } void Test2(CL0 x2) { x2 = x2.M1((dynamic)0) ?? x2; } } class CL0 { public T M1(int x) { return default(T); } public long M1(long x) { return x; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (22,16): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // return default(T); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(22, 16) ); } [Fact] public void DynamicInvocation_09() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(CL0? x1) { x1 = x1.M1((dynamic)0); } void Test2(CL0? x2) { x2 = x2.M1(0); } } class CL0 { public CL0 M1(int x) { return new CL0(); } public CL0 M1(long x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,14): warning CS8602: Dereference of a possibly null reference. // x1 = x1.M1((dynamic)0); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(9, 14), // (14,14): warning CS8602: Dereference of a possibly null reference. // x2 = x2.M1(0); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(14, 14) ); } [Fact] public void DynamicMemberAccess_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1(dynamic x1) { x1 = x1.M1; } void Test2(dynamic x2) { x2 = x2.M1 ?? x2; } void Test3(dynamic? x3) { dynamic y3 = x3.M1; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (19,22): warning CS8602: Dereference of a possibly null reference. // dynamic y3 = x3.M1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(19, 22) ); } [Fact] public void DynamicMemberAccess_02() { var source = @"class C { static void M(dynamic x) { x.F/*T:dynamic!*/.ToString(); var y = x.F; y/*T:dynamic!*/.ToString(); y = null; } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 13) ); comp.VerifyTypes(); } [Fact] public void DynamicObjectCreationExpression_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() {} void Test1() { dynamic? x1 = null; CL0 y1 = new CL0(x1); } void Test2(CL0 y2) { dynamic? x2 = null; CL0 z2 = new CL0(x2) ?? y2; } } class CL0 { public CL0(int x) { } public CL0(long x) { } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DynamicInvocation() { var source = @"class C { static void F(object x, object y) { } static void G(object? x, dynamic y) { F(x, y); if (x != null) F(y, x); } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29893: We should be able to report warnings // when all applicable methods agree on the nullability of particular parameters. // (For instance, x in F(x, y) above.) comp.VerifyDiagnostics(); } [Fact] public void NameOf_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(string x1, string? y1) { x1 = nameof(y1); } void Test2(string x2, string? y2) { string? z2 = nameof(y2); x2 = z2 ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void StringInterpolation_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(string x1, string? y1) { x1 = $""{y1}""; } void Test2(string x2, string? y2) { x2 = $""{y2}"" ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DelegateCreation_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(System.Action x1) { x1 = new System.Action(Main); } void Test2(System.Action x2) { x2 = new System.Action(Main) ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void DelegateCreation_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } CL0 M1(CL0 x) { throw new System.Exception(); } delegate CL0 D1(CL0 x); void Test1() { D1 x1 = new D1(M1); } CL0 M2(CL0 x) { throw new System.Exception(); } delegate CL0 D2(CL0 x); void Test2() { D2 x2 = new D2(M2); } } class CL0{} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,24): warning CS8621: Nullability of reference types in return type of 'CL0 C.M1(CL0 x)' doesn't match the target delegate 'C.D1'. // D1 x1 = new D1(M1); Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M1").WithArguments("CL0 C.M1(CL0 x)", "C.D1").WithLocation(13, 24), // (13,24): warning CS8622: Nullability of reference types in type of parameter 'x' of 'CL0 C.M1(CL0 x)' doesn't match the target delegate 'C.D1'. // D1 x1 = new D1(M1); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M1").WithArguments("x", "CL0 C.M1(CL0 x)", "C.D1").WithLocation(13, 24), // (21,24): warning CS8621: Nullability of reference types in return type of 'CL0 C.M2(CL0 x)' doesn't match the target delegate 'C.D2'. // D2 x2 = new D2(M2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M2").WithArguments("CL0 C.M2(CL0 x)", "C.D2").WithLocation(21, 24), // (21,24): warning CS8622: Nullability of reference types in type of parameter 'x' of 'CL0 C.M2(CL0 x)' doesn't match the target delegate 'C.D2'. // D2 x2 = new D2(M2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M2").WithArguments("x", "CL0 C.M2(CL0 x)", "C.D2").WithLocation(21, 24)); } [Fact] public void DelegateCreation_03() { var source = @"delegate void D(object x, object? y); class Program { static void Main() { _ = new D((object x1, object? y1) => { x1 = null; // 1 y1.ToString(); // 2 }); _ = new D((x2, y2) => { x2 = null; // 3 y2.ToString(); // 4 }); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 22), // (9,17): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(9, 17), // (13,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = null; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 22), // (14,17): warning CS8602: Dereference of a possibly null reference. // y2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(14, 17)); } [Fact] public void DelegateCreation_04() { var source = @"delegate object D1(); delegate object? D2(); class Program { static void F(object x, object? y) { x = null; // 1 y = 2; _ = new D1(() => x); // 2 _ = new D2(() => x); _ = new D1(() => y); _ = new D2(() => y); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 13), // (9,26): warning CS8603: Possible null reference return. // _ = new D1(() => x); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "x").WithLocation(9, 26)); } [Fact] [WorkItem(35549, "https://github.com/dotnet/roslyn/issues/35549")] public void DelegateCreation_05() { var source = @"delegate T D(); class Program { static T F() => throw null!; static void G() where T : class { _ = new D(F)!; _ = new D(F!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,25): error CS0119: 'T' is a type, which is not valid in the given context // _ = new D(F!); Diagnostic(ErrorCode.ERR_BadSKunknown, "T").WithArguments("T", "type").WithLocation(8, 25), // (8,28): error CS1525: Invalid expression term ')' // _ = new D(F!); Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(8, 28)); } [Fact] public void DelegateCreation_06() { var source = @"delegate T D(); class Program { static T F() => throw null!; static void G() where T : class { _ = new D(F)!; // 1 _ = new D(F!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,22): warning CS8621: Nullability of reference types in return type of 'T? Program.F()' doesn't match the target delegate 'D'. // _ = new D(F)!; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F").WithArguments("T? Program.F()", "D").WithLocation(7, 22)); } [Fact] public void DelegateCreation_07() { var source = @"delegate T D(); class Program { static T F() => throw null!; static void G() where T : class { _ = new D(() => F())!; _ = new D(() => F()!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void DelegateCreation_08() { var source = @"delegate T D(); class Program { static T F() => throw null!; static void G() where T : class { _ = new D(() => F())!; // 1 _ = new D(() => F()!); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,28): warning CS8603: Possible null reference return. // _ = new D(() => F())!; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "F()").WithLocation(7, 28)); } [Fact] public void DelegateCreation_09() { var source = @"delegate void D(); class C { void F() { } static void M() { D d = default(C).F; // 1 _ = new D(default(C).F); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,15): warning CS8602: Dereference of a possibly null reference. // D d = default(C).F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(C)").WithLocation(7, 15), // (8,19): warning CS8602: Dereference of a possibly null reference. // _ = new D(default(C).F); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(C)").WithLocation(8, 19)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_ReturnType_01() { var source = @"delegate T D(); interface I { } interface IIn { } interface IOut { } class C { static T F() => throw null!; static void Main() { _ = new D(() => F()); // 1 _ = new D(() => F()); _ = new D>(() => F>()); // 2 _ = new D>(() => F>()); // 3 _ = new D>(() => F>()); _ = new D>(() => F>()); // 4 _ = new D>(() => F>()); // 5 _ = new D>(() => F>()); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,33): warning CS8603: Possible null reference return. // _ = new D(() => F()); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "F()").WithLocation(10, 33), // (12,36): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // _ = new D>(() => F>()); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "F>()").WithArguments("I", "I").WithLocation(12, 36), // (13,37): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // _ = new D>(() => F>()); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "F>()").WithArguments("I", "I").WithLocation(13, 37), // (15,39): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // _ = new D>(() => F>()); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "F>()").WithArguments("IIn", "IIn").WithLocation(15, 39), // (16,39): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // _ = new D>(() => F>()); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "F>()").WithArguments("IOut", "IOut").WithLocation(16, 39)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_ReturnType_02() { var source = @"delegate T D(); interface I { } interface IIn { } interface IOut { } class C { static T F() => throw null!; static void Main() { _ = new D(F); // 1 _ = new D(F); _ = new D>(F>); // 2 _ = new D>(F>); // 3 _ = new D>(F>); _ = new D>(F>); // 4 _ = new D>(F>); // 5 _ = new D>(F>); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,27): warning CS8621: Nullability of reference types in return type of 'object? C.F()' doesn't match the target delegate 'D'. // _ = new D(F); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F").WithArguments("object? C.F()", "D").WithLocation(10, 27), // (12,30): warning CS8621: Nullability of reference types in return type of 'I C.F>()' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("I C.F>()", "D>").WithLocation(12, 30), // (13,31): warning CS8621: Nullability of reference types in return type of 'I C.F>()' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("I C.F>()", "D>").WithLocation(13, 31), // (15,33): warning CS8621: Nullability of reference types in return type of 'IIn C.F>()' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("IIn C.F>()", "D>").WithLocation(15, 33), // (16,33): warning CS8621: Nullability of reference types in return type of 'IOut C.F>()' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("IOut C.F>()", "D>").WithLocation(16, 33)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_Parameter_01() { var source = @"delegate void D(T t1); interface I { } interface IIn { } interface IOut { } class C { static void Main() { // parameter name is different than delegate to ensure that diagnostics refer to the correct names _ = new D((object? t2) => { }); // 1 _ = new D((object t2) => { }); // 2 _ = new D>((I t2) => { }); // 3 _ = new D>((I t2) => { }); // 4 _ = new D>((IIn t2) => { }); // 5 _ = new D>((IIn t2) => { }); // 6 _ = new D>((IOut t2) => { }); // 7 _ = new D>((IOut t2) => { }); // 8 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,40): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((object? t2) => { }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D").WithLocation(10, 40), // (11,40): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((object t2) => { }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D").WithLocation(11, 40), // (12,46): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((I t2) => { }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(12, 46), // (13,46): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((I t2) => { }); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(13, 46), // (14,50): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((IIn t2) => { }); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(14, 50), // (15,50): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((IIn t2) => { }); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(15, 50), // (16,52): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((IOut t2) => { }); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(16, 52), // (17,52): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((IOut t2) => { }); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(17, 52)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_Parameter_02() { var source = @"delegate void D(T t1); interface I { } interface IIn { } interface IOut { } class C { // parameter name is different than delegate to ensure that diagnostics refer to the correct names static void F(T t2) { } static void Main() { _ = new D(F); _ = new D(F); // 1 _ = new D>(F>); // 2 _ = new D>(F>); // 3 _ = new D>(F>); // 4 _ = new D>(F>); _ = new D>(F>); _ = new D>(F>); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,28): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F(object t2)' doesn't match the target delegate 'D'. // _ = new D(F); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t2", "void C.F(object t2)", "D").WithLocation(12, 28), // (13,30): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(I t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(I t2)", "D>").WithLocation(13, 30), // (14,31): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(I t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(I t2)", "D>").WithLocation(14, 31), // (15,32): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(IIn t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(IIn t2)", "D>").WithLocation(15, 32), // (18,34): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(IOut t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(IOut t2)", "D>").WithLocation(18, 34)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_OutParameter_01() { var source = @"delegate void D(out T t1); interface I { } interface IIn { } interface IOut { } class C { static void Main() { // parameter name is different than delegate to ensure that diagnostics refer to the correct names _ = new D((out object? t2) => t2 = default!); // 1 _ = new D((out object t2) => t2 = default!); // 2 _ = new D>((out I t2) => t2 = default!); // 3 _ = new D>((out I t2) => t2 = default!); // 4 _ = new D>((out IIn t2) => t2 = default!); // 5 _ = new D>((out IIn t2) => t2 = default!); // 6 _ = new D>((out IOut t2) => t2 = default!); // 7 _ = new D>((out IOut t2) => t2 = default!); // 8 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,44): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((out object? t2) => t2 = default!); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D").WithLocation(10, 44), // (11,44): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((out object t2) => t2 = default!); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D").WithLocation(11, 44), // (12,50): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((out I t2) => t2 = default!); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(12, 50), // (13,50): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((out I t2) => t2 = default!); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(13, 50), // (14,54): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((out IIn t2) => t2 = default!); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(14, 54), // (15,54): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((out IIn t2) => t2 = default!); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(15, 54), // (16,56): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((out IOut t2) => t2 = default!); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(16, 56), // (17,56): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((out IOut t2) => t2 = default!); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(17, 56)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_OutParameter_02() { var source = @"delegate void D(out T t1); interface I { } interface IIn { } interface IOut { } class C { // parameter name is different than delegate to ensure that diagnostics refer to the correct names static void F(out T t2) { t2 = default!; } static void Main() { _ = new D(F); // 1 _ = new D(F); _ = new D>(F>); // 2 _ = new D>(F>); // 3 _ = new D>(F>); _ = new D>(F>); // 4 _ = new D>(F>); // 5 _ = new D>(F>); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,27): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F(out object? t2)' doesn't match the target delegate 'D'. // _ = new D(F); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t2", "void C.F(out object? t2)", "D").WithLocation(11, 27), // (13,30): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(out I t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(out I t2)", "D>").WithLocation(13, 30), // (14,31): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(out I t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(out I t2)", "D>").WithLocation(14, 31), // (16,33): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(out IIn t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(out IIn t2)", "D>").WithLocation(16, 33), // (17,33): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(out IOut t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(out IOut t2)", "D>").WithLocation(17, 33)); } [Fact] [WorkItem(32563, "https://github.com/dotnet/roslyn/issues/32563")] public void DelegateCreation_InParameter_01() { var source = @"delegate void D(in T t1); interface I { } interface IIn { } interface IOut { } class C { static void Main() { // parameter name is different than delegate to ensure that diagnostics refer to the correct names _ = new D((in object? t2) => { }); // 1 _ = new D((in object t2) => { }); // 2 _ = new D>((in I t2) => { }); // 3 _ = new D>((in I t2) => { }); // 4 _ = new D>((in IIn t2) => { }); // 5 _ = new D>((in IIn t2) => { }); // 6 _ = new D>((in IOut t2) => { }); // 7 _ = new D>((in IOut t2) => { }); // 8 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,43): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((in object? t2) => { }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D").WithLocation(10, 43), // (11,43): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((in object t2) => { }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D").WithLocation(11, 43), // (12,49): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((in I t2) => { }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(12, 49), // (13,49): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((in I t2) => { }); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(13, 49), // (14,53): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((in IIn t2) => { }); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(14, 53), // (15,53): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((in IIn t2) => { }); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(15, 53), // (16,55): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((in IOut t2) => { }); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(16, 55), // (17,55): warning CS8622: Nullability of reference types in type of parameter 't2' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((in IOut t2) => { }); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t2", "lambda expression", "D>").WithLocation(17, 55)); } [Fact] [WorkItem(32563, "https://github.com/dotnet/roslyn/issues/32563")] public void DelegateCreation_InParameter_02() { var source = @"delegate void D(in T t1); interface I { } interface IIn { } interface IOut { } class C { // parameter name is different than delegate to ensure that diagnostics refer to the correct names static void F(in T t2) { } static void Main() { _ = new D(F); _ = new D(F); // 1 _ = new D>(F>); // 2 _ = new D>(F>); // 3 _ = new D>(F>); // 4 _ = new D>(F>); _ = new D>(F>); _ = new D>(F>); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,28): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F(in object t2)' doesn't match the target delegate 'D'. // _ = new D(F); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t2", "void C.F(in object t2)", "D").WithLocation(12, 28), // (13,30): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(in I t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(in I t2)", "D>").WithLocation(13, 30), // (14,31): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(in I t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(in I t2)", "D>").WithLocation(14, 31), // (15,32): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(in IIn t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(in IIn t2)", "D>").WithLocation(15, 32), // (18,34): warning CS8622: Nullability of reference types in type of parameter 't2' of 'void C.F>(in IOut t2)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t2", "void C.F>(in IOut t2)", "D>").WithLocation(18, 34)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_RefParameter_01() { var source = @"delegate void D(ref T t); interface I { } interface IIn { } interface IOut { } class C { static void Main() { _ = new D((ref object? t) => { }); // 1 _ = new D((ref object t) => { }); // 2 _ = new D>((ref I t) => { }); // 3 _ = new D>((ref I t) => { }); // 4 _ = new D>((ref IIn t) => { }); // 5 _ = new D>((ref IIn t) => { }); // 6 _ = new D>((ref IOut t) => { }); // 7 _ = new D>((ref IOut t) => { }); // 8 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,43): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((ref object? t) => { }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D").WithLocation(9, 43), // (10,43): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D'. // _ = new D((ref object t) => { }); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D").WithLocation(10, 43), // (11,49): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((ref I t) => { }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D>").WithLocation(11, 49), // (12,49): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((ref I t) => { }); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D>").WithLocation(12, 49), // (13,53): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((ref IIn t) => { }); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D>").WithLocation(13, 53), // (14,53): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((ref IIn t) => { }); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D>").WithLocation(14, 53), // (15,55): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((ref IOut t) => { }); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D>").WithLocation(15, 55), // (16,55): warning CS8622: Nullability of reference types in type of parameter 't' of 'lambda expression' doesn't match the target delegate 'D>'. // _ = new D>((ref IOut t) => { }); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "=>").WithArguments("t", "lambda expression", "D>").WithLocation(16, 55)); } [Fact] [WorkItem(32499, "https://github.com/dotnet/roslyn/issues/32499")] public void DelegateCreation_RefParameter_02() { var source = @"delegate void D(ref T t); interface I { } interface IIn { } interface IOut { } class C { static void F(ref T t) { } static void Main() { _ = new D(F); // 1 _ = new D(F); // 2 _ = new D>(F>); // 3 _ = new D>(F>); // 4 _ = new D>(F>); // 5 _ = new D>(F>); // 6 _ = new D>(F>); // 7 _ = new D>(F>); // 8 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,27): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(ref object? t)' doesn't match the target delegate 'D'. // _ = new D(F); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(ref object? t)", "D").WithLocation(10, 27), // (11,28): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(ref object t)' doesn't match the target delegate 'D'. // _ = new D(F); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(ref object t)", "D").WithLocation(11, 28), // (12,30): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref I t)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref I t)", "D>").WithLocation(12, 30), // (13,31): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref I t)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref I t)", "D>").WithLocation(13, 31), // (14,32): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IIn t)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IIn t)", "D>").WithLocation(14, 32), // (15,33): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IIn t)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IIn t)", "D>").WithLocation(15, 33), // (16,33): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IOut t)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IOut t)", "D>").WithLocation(16, 33), // (17,34): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IOut t)' doesn't match the target delegate 'D>'. // _ = new D>(F>); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IOut t)", "D>").WithLocation(17, 34)); } [Fact] public void IdentityConversion_DelegateReturnType() { var source = @"delegate T D(); interface I { } interface IIn { } interface IOut { } class C { static T F() => throw new System.Exception(); static void G() { D a = F; D b = F; D> c = F>; D> d = F>; D> e = F>; D> f = F>; D> g = F>; D> h = F>; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,23): warning CS8621: Nullability of reference types in return type of 'object? C.F()' doesn't match the target delegate 'D'. // D a = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F").WithArguments("object? C.F()", "D").WithLocation(10, 23), // (12,26): warning CS8621: Nullability of reference types in return type of 'I C.F>()' doesn't match the target delegate 'D>'. // D> c = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("I C.F>()", "D>").WithLocation(12, 26), // (13,27): warning CS8621: Nullability of reference types in return type of 'I C.F>()' doesn't match the target delegate 'D>'. // D> d = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("I C.F>()", "D>").WithLocation(13, 27), // (15,29): warning CS8621: Nullability of reference types in return type of 'IIn C.F>()' doesn't match the target delegate 'D>'. // D> f = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("IIn C.F>()", "D>").WithLocation(15, 29), // (16,29): warning CS8621: Nullability of reference types in return type of 'IOut C.F>()' doesn't match the target delegate 'D>'. // D> g = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F>").WithArguments("IOut C.F>()", "D>").WithLocation(16, 29)); } [Fact] public void IdentityConversion_DelegateParameter_01() { var source = @"delegate void D(T t); interface I { } interface IIn { } interface IOut { } class C { static void F(T t) { } static void G() { D a = F; D b = F; D> c = F>; D> d = F>; D> e = F>; D> f = F>; D> g = F>; D> h = F>; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,24): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(object t)' doesn't match the target delegate 'D'. // D b = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(object t)", "D").WithLocation(11, 24), // (12,26): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(I t)' doesn't match the target delegate 'D>'. // D> c = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(I t)", "D>").WithLocation(12, 26), // (13,27): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(I t)' doesn't match the target delegate 'D>'. // D> d = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(I t)", "D>").WithLocation(13, 27), // (14,28): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(IIn t)' doesn't match the target delegate 'D>'. // D> e = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(IIn t)", "D>").WithLocation(14, 28), // (17,30): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(IOut t)' doesn't match the target delegate 'D>'. // D> h = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(IOut t)", "D>").WithLocation(17, 30)); } [Fact] [WorkItem(29844, "https://github.com/dotnet/roslyn/issues/29844")] public void IdentityConversion_DelegateParameter_02() { var source = @"delegate T D(); class A { internal T M() => throw new System.NotImplementedException(); } class B { static A F(T t) => throw null!; static void G(object? o) { var x = F(o); D d = x.M; D e = x.M; // 1 if (o == null) return; var y = F(o); d = y.M; e = y.M; d = (D)y.M; e = (D)y.M; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,23): warning CS8621: Nullability of reference types in return type of 'object? A.M()' doesn't match the target delegate 'D'. // D e = x.M; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.M").WithArguments("object? A.M()", "D").WithLocation(13, 23)); } [Fact] [WorkItem(29844, "https://github.com/dotnet/roslyn/issues/29844")] public void IdentityConversion_DelegateOutParameter() { var source = @"delegate void D(out T t); interface I { } interface IIn { } interface IOut { } class C { static void F(out T t) { t = default!; } static void G() { D a = F; D b = F; D> c = F>; D> d = F>; D> e = F>; D> f = F>; D> g = F>; D> h = F>; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,23): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(out object? t)' doesn't match the target delegate 'D'. // D a = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(out object? t)", "D").WithLocation(10, 23), // (12,26): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(out I t)' doesn't match the target delegate 'D>'. // D> c = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out I t)", "D>").WithLocation(12, 26), // (13,27): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(out I t)' doesn't match the target delegate 'D>'. // D> d = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out I t)", "D>").WithLocation(13, 27), // (15,29): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(out IIn t)' doesn't match the target delegate 'D>'. // D> f = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out IIn t)", "D>").WithLocation(15, 29), // (16,29): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(out IOut t)' doesn't match the target delegate 'D>'. // D> g = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(out IOut t)", "D>").WithLocation(16, 29) ); } [Fact] [WorkItem(32563, "https://github.com/dotnet/roslyn/issues/32563")] public void IdentityConversion_DelegateInParameter() { var source = @"delegate void D(in T t); interface I { } interface IIn { } interface IOut { } class C { static void F(in T t) { } static void G() { D a = F; D b = F; D> c = F>; D> d = F>; D> e = F>; D> f = F>; D> g = F>; D> h = F>; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,24): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(in object t)' doesn't match the target delegate 'D'. // D b = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(in object t)", "D").WithLocation(11, 24), // (12,26): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(in I t)' doesn't match the target delegate 'D>'. // D> c = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(in I t)", "D>").WithLocation(12, 26), // (13,27): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(in I t)' doesn't match the target delegate 'D>'. // D> d = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(in I t)", "D>").WithLocation(13, 27), // (14,28): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(in IIn t)' doesn't match the target delegate 'D>'. // D> e = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(in IIn t)", "D>").WithLocation(14, 28), // (17,30): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(in IOut t)' doesn't match the target delegate 'D>'. // D> h = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(in IOut t)", "D>").WithLocation(17, 30) ); } [Fact] public void IdentityConversion_DelegateRefParameter() { var source = @"delegate void D(ref T t); interface I { } interface IIn { } interface IOut { } class C { static void F(ref T t) { } static void G() { D a = F; D b = F; D> c = F>; D> d = F>; D> e = F>; D> f = F>; D> g = F>; D> h = F>; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,23): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(ref object? t)' doesn't match the target delegate 'D'. // D a = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(ref object? t)", "D").WithLocation(10, 23), // (11,24): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(ref object t)' doesn't match the target delegate 'D'. // D b = F; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F").WithArguments("t", "void C.F(ref object t)", "D").WithLocation(11, 24), // (12,26): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref I t)' doesn't match the target delegate 'D>'. // D> c = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref I t)", "D>").WithLocation(12, 26), // (13,27): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref I t)' doesn't match the target delegate 'D>'. // D> d = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref I t)", "D>").WithLocation(13, 27), // (14,28): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IIn t)' doesn't match the target delegate 'D>'. // D> e = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IIn t)", "D>").WithLocation(14, 28), // (15,29): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IIn t)' doesn't match the target delegate 'D>'. // D> f = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IIn t)", "D>").WithLocation(15, 29), // (16,29): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IOut t)' doesn't match the target delegate 'D>'. // D> g = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IOut t)", "D>").WithLocation(16, 29), // (17,30): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F>(ref IOut t)' doesn't match the target delegate 'D>'. // D> h = F>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F>").WithArguments("t", "void C.F>(ref IOut t)", "D>").WithLocation(17, 30)); } [Fact] public void Base_01() { CSharpCompilation c = CreateCompilation(new[] { @" class Base { public virtual void Test() {} } class C : Base { static void Main() { } public override void Test() { base.Test(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void Base_02() { var source0 = @"public abstract class A { } public class B : A where T : B { }"; var comp0 = CreateCompilation(source0, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics(); CompileAndVerify(comp0, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var b = m.GlobalNamespace.GetTypeMember("B"); Assert.Equal("A", b.BaseTypeNoUseSiteDiagnostics.ToTestDisplayString(true)); } } [Fact] public void Base_03() { var source0 = @"public abstract class A { } public class B : A where T : B { }"; var comp0 = CreateCompilation(source0, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics(); CompileAndVerify(comp0, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var b = m.GlobalNamespace.GetTypeMember("B"); Assert.Equal("A", b.BaseTypeNoUseSiteDiagnostics.ToTestDisplayString(true)); } } [Fact] public void TypeOf_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(System.Type x1) { x1 = typeof(C); } void Test2(System.Type x2) { x2 = typeof(C) ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] [WorkItem(29894, "https://github.com/dotnet/roslyn/issues/29894")] public void TypeOf_02() { CSharpCompilation c = CreateCompilation(new[] { @" class List { } class C where TClass : class where TStruct : struct { void M() { _ = typeof(C?); _ = typeof(T?); _ = typeof(TClass?); _ = typeof(TStruct?); _ = typeof(List); _ = typeof(List); _ = typeof(List); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,13): error CS8639: The typeof operator cannot be used on a nullable reference type // _ = typeof(C?); Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(C?)").WithLocation(9, 13), // (10,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // _ = typeof(T?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(10, 20), // (11,13): error CS8639: The typeof operator cannot be used on a nullable reference type // _ = typeof(TClass?); Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(TClass?)").WithLocation(11, 13), // (13,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // _ = typeof(List); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(13, 25)); } [Fact] public void Default_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(C x1) { x1 = default(C); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = default(C); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(C)").WithLocation(10, 14) ); } [Fact] public void Default_NonNullable() { var source = @"class C { static void Main() { var s = default(string); s.ToString(); var i = default(int); i.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("System.Int32", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Default_Nullable() { var source = @"class C { static void Main() { var s = default(string?); s.ToString(); var i = default(int?); i.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9) ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("System.String", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("System.Int32?", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Annotated, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Default_TUnconstrained() { var source = @"class C { static void F() { var s = default(T); s.ToString(); var t = default(T?); t.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (5,17): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var s = default(T); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(5, 17), // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9), // (7,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // var t = default(T?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 25), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9) ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); Assert.Equal("T", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); // https://github.com/dotnet/roslyn/issues/29856: Is T correct? Assert.Equal("T", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void Default_TClass() { var source = @"class C { static void F() where T : class { var s = default(T); s.ToString(); var t = default(T?); t.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); // https://github.com/dotnet/roslyn/issues/26198 public API should show inferred nullability Assert.Equal("T", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("T", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Oblivious, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void DefaultInferred_NonNullable() { var source = @"class C { static void Main() { string s = default; s.ToString(); int i = default; i.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // string s = default; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 20), // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); Assert.Equal("System.String!", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.NotAnnotated, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("System.Int32", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.NotAnnotated, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void DefaultInferred_Nullable() { var source = @"class C { static void Main() { string? s = default; s.ToString(); int? i = default; i.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9) ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); Assert.Equal("System.String?", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Annotated, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("System.Int32?", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Annotated, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void DefaultInferred_TUnconstrained() { var source = @"class C { static void F() { T s = default; s.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); // https://github.com/dotnet/roslyn/issues/29895: Improve this diagnostic. default is the cause of the error, but is not mentioned in the diagnostic. comp.VerifyDiagnostics( // (5,15): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // T s = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(5, 15), // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9) ); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); Assert.Equal("T", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.NotAnnotated, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] public void DefaultInferred_TClass() { var source = @"class C { static void F() where T : class { T s = default; s.ToString(); T? t = default; t.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (5,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T s = default; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 15), // (6,9): warning CS8602: Dereference of a possibly null reference. // s.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(8, 9)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarators = tree.GetRoot().DescendantNodes().OfType().ToArray(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[0]); Assert.Equal("T!", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.NotAnnotated, symbol.TypeWithAnnotations.NullableAnnotation); symbol = (LocalSymbol)model.GetDeclaredSymbol(declarators[1]); Assert.Equal("T?", symbol.TypeWithAnnotations.ToTestDisplayString(true)); Assert.Equal(NullableAnnotation.Annotated, symbol.TypeWithAnnotations.NullableAnnotation); } [Fact] [WorkItem(29896, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference() { var source = @"class C { static void F((object? a, object? b) t) { if (t.b == null) return; object? x; object? y; (x, y) = t; x.ToString(); y.ToString(); } static void F(object? a, object? b) { if (b == null) return; object? x; object? y; (x, y) = (a, b); x.ToString(); y.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(9, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(18, 9)); } [Fact] public void IdentityConversion_DeconstructionAssignment() { var source = @"interface IIn { } interface IOut { } class C { void Deconstruct(out IIn x, out IOut y) { throw new System.NotImplementedException(); } static void F(C c) { IIn x; IOut y; (x, y) = c; } static void G(C c) { IIn x; IOut y; (x, y) = c; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,10): warning CS8624: Argument of type 'IIn' cannot be used as an output of type 'IIn' for parameter 'x' in 'void C.Deconstruct(out IIn x, out IOut y)' due to differences in the nullability of reference types. // (x, y) = c; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x").WithArguments("IIn", "IIn", "x", "void C.Deconstruct(out IIn x, out IOut y)").WithLocation(13, 10), // (19,13): warning CS8624: Argument of type 'IOut' cannot be used as an output of type 'IOut' for parameter 'y' in 'void C.Deconstruct(out IIn x, out IOut y)' due to differences in the nullability of reference types. // (x, y) = c; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "y").WithArguments("IOut", "IOut", "y", "void C.Deconstruct(out IIn x, out IOut y)").WithLocation(19, 13) ); } [Fact] [WorkItem(29618, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference_01() { var source = @"class C { static void M() { (var x, var y) = ((string?)null, string.Empty); x.ToString(); // 1 y.ToString(); x = null; y = null; // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9), // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(9, 13) ); } [Fact] [WorkItem(29618, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference_02() { var source = @"class C { static (string?, string) F() => (string.Empty, string.Empty); static void G() { (var x, var y) = F(); x.ToString(); // 1 y.ToString(); x = null; y = null; // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9), // (10,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 13) ); } [Fact] [WorkItem(29618, "https://github.com/dotnet/roslyn/issues/29618")] public void DeconstructionTypeInference_03() { var source = @"class C { void Deconstruct(out string? x, out string y) { x = string.Empty; y = string.Empty; } static void M() { (var x, var y) = new C(); x.ToString(); y.ToString(); x = null; y = null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(11, 9), // (14,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 13)); } [Fact] public void DeconstructionTypeInference_04() { var source = @"class C { static (string?, string) F() => (null, string.Empty); static void G() { string x; string? y; var t = ((x, y) = F()); _ = t/*T:(string x, string y)*/; t.x.ToString(); // 1 t.y.ToString(); t.x = null; t.y = null; // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/33011: Deconstruction should infer string? for x, // string! for y, and (string?, string!) for t. comp.VerifyDiagnostics( // (8,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // var t = ((x, y) = F()); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "F()").WithLocation(8, 27) ); comp.VerifyTypes(); } [Fact] public void DeconstructionTypeInference_05() { var source = @"using System; using System.Collections.Generic; class C { static IEnumerable<(string, string?)> F() => throw new Exception(); static void G() { foreach ((var x, var y) in F()) { x.ToString(); y.ToString(); // 1 } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(11, 13) ); } [Fact] public void Discard_01() { var source = @"class C { static void F((object, object?) t) { object? x; ((_, x) = t).Item1.ToString(); ((x, _) = t).Item2.ToString(); } }"; // https://github.com/dotnet/roslyn/issues/33011: Should report WRN_NullReferenceReceiver. var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); //// (7,9): warning CS8602: Dereference of a possibly null reference. //// ((x, _) = t).Item2.ToString(); //Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((x, _) = t).Item2").WithLocation(7, 9)); } [Fact] public void Discard_02() { // https://github.com/dotnet/roslyn/issues/29635 Need to re-infer discards var source = @"#nullable disable class C { #nullable enable void F(object o1, object? o2, C o3, C o4) { _ /*T:object?*/ = o1; _ /*T:object?*/ = o2; _ /*T:C?*/ = o3; _ /*T:C?*/ = o4; } #nullable disable void F(C o) { _ /*T:C?*/ = o; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void Discard_03() { // https://github.com/dotnet/roslyn/issues/33393 Need to re-infer discards. // The types below should have non-oblivious type arguments in the expected results. var source = @"#nullable disable class C { #nullable enable void F(bool b, object o1, object? o2, C o3, C o4) { _ /*T:object?*/ = (b ? o1 : o2); _ /*T:C?*/ = (b ? o3 : o4); // 1 _ /*T:C?*/ = (b ? o4 : o3); // 2 _ /*T:C?*/ = (b ? o3 : o5); _ /*T:C?*/ = (b ? o4 : o5); } #nullable disable static C o5 = null; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,40): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // _ /*T:C?*/ = (b ? o3 : o4); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "o4").WithArguments("C", "C").WithLocation(8, 40), // (9,35): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // _ /*T:C?*/ = (b ? o4 : o3); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "o4").WithArguments("C", "C").WithLocation(9, 35) ); comp.VerifyTypes(); } [Fact] public void Discard_04() { var source = @"#nullable disable class C { #nullable enable void F(bool b, object o1) { (_ /*T:object?*/ = o1) /*T:object!*/.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void BinaryOperator_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(string? x1, string? y1) { string z1 = x1 + y1; } void Test2(string? x2, string? y2) { string z2 = x2 + y2 ?? """"; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void BinaryOperator_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(dynamic? x1, dynamic? y1) { dynamic z1 = x1 + y1; } void Test2(dynamic? x2, dynamic? y2) { dynamic z2 = x2 + y2 ?? """"; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void BinaryOperator_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(string? x1, CL0? y1) { CL0? z1 = x1 + y1; CL0 u1 = z1 ?? new CL0(); } void Test2(string? x2, CL1? y2) { CL1 z2 = x2 + y2; } void Test3(string x3, CL0? y3, CL2 z3) { CL2 u3 = x3 + y3 + z3; } void Test4(string x4, CL1 y4, CL2 z4) { CL2 u4 = x4 + y4 + z4; } } class CL0 { public static CL0 operator + (string? x, CL0 y) { return y; } } class CL1 { public static CL1? operator + (string x, CL1? y) { return y; } } class CL2 { public static CL2 operator + (CL0 x, CL2 y) { return y; } public static CL2 operator + (CL1 x, CL2 y) { return y; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,24): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. // CL0? z1 = x1 + y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(10, 24), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1? CL1.operator +(string x, CL1? y)'. // CL1 z2 = x2 + y2; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL1? CL1.operator +(string x, CL1? y)").WithLocation(16, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = x2 + y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2 + y2").WithLocation(16, 18), // (21,23): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. // CL2 u3 = x3 + y3 + z3; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y3").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(21, 23), // (26,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL2 CL2.operator +(CL1 x, CL2 y)'. // CL2 u4 = x4 + y4 + z4; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4 + y4").WithArguments("x", "CL2 CL2.operator +(CL1 x, CL2 y)").WithLocation(26, 18) ); } [Fact] public void BinaryOperator_03_WithDisallowAndAllowNull() { CSharpCompilation c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class CL0 { void Test1(string? x1, CL0? y1) { CL0? z1 = x1 + y1; CL0 u1 = z1 ?? new CL0(); } public static CL0 operator + (string? x, [AllowNull] CL0 y) => throw null!; } class CL1 { void Test2(string? x2, CL1? y2) { CL1 z2 = x2 + y2; // 1, 2 } public static CL1? operator + ([AllowNull] string x, [DisallowNull] CL1? y) => throw null!; } class CL2 { void Test3(string x3, CL0? y3, CL2 z3) { CL2 u3 = x3 + y3 + z3; } void Test4(string x4, CL1 y4, CL2 z4) { CL2 u4 = x4 + y4 + z4; } public static CL2 operator + ([AllowNull] CL0 x, CL2 y) => throw null!; public static CL2 operator + ([AllowNull] CL1 x, CL2 y) => throw null!; } ", AllowNullAttributeDefinition, DisallowNullAttributeDefinition }); // Analyze operator call properly (honoring [Disallow|Allow|Maybe|NotNull] attribute annotations) https://github.com/dotnet/roslyn/issues/32671 c.VerifyDiagnostics( // (8,24): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. // CL0? z1 = x1 + y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(8, 24), // (19,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1? CL1.operator +(string x, CL1? y)'. // CL1 z2 = x2 + y2; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL1? CL1.operator +(string x, CL1? y)").WithLocation(19, 18), // (19,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 z2 = x2 + y2; // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2 + y2").WithLocation(19, 18), // (29,23): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator +(string? x, CL0 y)'. // CL2 u3 = x3 + y3 + z3; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y3").WithArguments("y", "CL0 CL0.operator +(string? x, CL0 y)").WithLocation(29, 23), // (34,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL2 CL2.operator +(CL1 x, CL2 y)'. // CL2 u4 = x4 + y4 + z4; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4 + y4").WithArguments("x", "CL2 CL2.operator +(CL1 x, CL2 y)").WithLocation(34, 18) ); } [Fact] public void BinaryOperator_03_WithMaybeAndNotNull() { CSharpCompilation c = CreateNullableCompilation(new[] { @" using System.Diagnostics.CodeAnalysis; class CL0 { void Test1(string x1, CL0 y1) { CL0 z1 = x1 + y1; // 1 } [return: MaybeNull] public static CL0 operator + (string x, CL0 y) => throw null!; } class CL1 { void Test2(string x2, CL1 y2) { CL1 z2 = x2 + y2; } [return: NotNull] public static CL1? operator + (string x, CL1 y) => throw null!; } class CL2 { void Test3(string x3, CL0 y3, CL2 z3) { CL2 u3 = x3 + y3 + z3; // 2, 3 } void Test4(string x4, CL1 y4, CL2 z4) { CL2 u4 = x4 + y4 + z4; } [return: MaybeNull] public static CL2 operator + (CL0 x, CL2 y) => throw null!; [return: NotNull] public static CL2? operator + (CL1 x, CL2 y) => throw null!; } ", MaybeNullAttributeDefinition, NotNullAttributeDefinition }); c.VerifyDiagnostics( // (8,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 z1 = x1 + y1; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1 + y1").WithLocation(8, 18), // (28,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL2 CL2.operator +(CL0 x, CL2 y)'. // CL2 u3 = x3 + y3 + z3; // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x3 + y3").WithArguments("x", "CL2 CL2.operator +(CL0 x, CL2 y)").WithLocation(28, 18), // (28,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL2 u3 = x3 + y3 + z3; // 2, 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 + y3 + z3").WithLocation(28, 18) ); } [Fact] public void BinaryOperator_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1, CL0? y1) { CL0? z1 = x1 && y1; CL0 u1 = z1; } void Test2(CL0 x2, CL0? y2) { CL0? z2 = x2 && y2; CL0 u2 = z2 ?? new CL0(); } } class CL0 { public static CL0 operator &(CL0 x, CL0? y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0 x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'bool CL0.operator false(CL0 x)'. // CL0? z1 = x1 && y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "bool CL0.operator false(CL0 x)").WithLocation(10, 19), // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator &(CL0 x, CL0? y)'. // CL0? z1 = x1 && y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator &(CL0 x, CL0? y)").WithLocation(10, 19) ); } [Fact] public void BinaryOperator_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1, CL0? y1) { CL0? z1 = x1 && y1; } } class CL0 { public static CL0 operator &(CL0? x, CL0 y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0 x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'bool CL0.operator false(CL0 x)'. // CL0? z1 = x1 && y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "bool CL0.operator false(CL0 x)").WithLocation(10, 19), // (10,25): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator &(CL0? x, CL0 y)'. // CL0? z1 = x1 && y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL0 CL0.operator &(CL0? x, CL0 y)").WithLocation(10, 25) ); } [Fact] public void BinaryOperator_06() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1, CL0? y1) { CL0? z1 = x1 && y1; } } class CL0 { public static CL0 operator &(CL0? x, CL0? y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0? x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void BinaryOperator_07() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1, CL0? y1) { CL0? z1 = x1 || y1; } } class CL0 { public static CL0 operator |(CL0? x, CL0? y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0? x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'bool CL0.operator true(CL0 x)'. // CL0? z1 = x1 || y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "bool CL0.operator true(CL0 x)").WithLocation(10, 19) ); } [Fact] public void BinaryOperator_08() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1, CL0? y1) { CL0? z1 = x1 || y1; } } class CL0 { public static CL0 operator |(CL0? x, CL0? y) { return new CL0(); } public static bool operator true(CL0? x) { return false; } public static bool operator false(CL0 x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void BinaryOperator_09() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1, CL0 y1, CL0 z1) { CL0? u1 = x1 && y1 || z1; } } class CL0 { public static CL0? operator &(CL0 x, CL0 y) { return new CL0(); } public static CL0 operator |(CL0 x, CL0 y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0 x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'bool CL0.operator true(CL0 x)'. // CL0? u1 = x1 && y1 || z1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1 && y1").WithArguments("x", "bool CL0.operator true(CL0 x)").WithLocation(10, 19), // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator |(CL0 x, CL0 y)'. // CL0? u1 = x1 && y1 || z1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1 && y1").WithArguments("x", "CL0 CL0.operator |(CL0 x, CL0 y)").WithLocation(10, 19) ); } [Fact] public void BinaryOperator_10() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1, CL0? y1, CL0? z1) { CL0? u1 = x1 && y1 || z1; } void Test2(CL0 x2, CL0? y2, CL0? z2) { CL0? u1 = x2 && y2 || z2; } } class CL0 { public static CL0 operator &(CL0? x, CL0? y) { return new CL0(); } public static CL0 operator |(CL0 x, CL0? y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0? x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void BinaryOperator_11() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(System.Action x1, System.Action y1) { System.Action u1 = x1 + y1; } void Test2(System.Action x2, System.Action y2) { System.Action u2 = x2 + y2 ?? x2; } void Test3(System.Action? x3, System.Action y3) { System.Action u3 = x3 + y3; } void Test4(System.Action? x4, System.Action y4) { System.Action u4 = x4 + y4 ?? y4; } void Test5(System.Action x5, System.Action? y5) { System.Action u5 = x5 + y5; } void Test6(System.Action x6, System.Action? y6) { System.Action u6 = x6 + y6 ?? x6; } void Test7(System.Action? x7, System.Action? y7) { System.Action u7 = x7 + y7; } void Test8(System.Action x8, System.Action y8) { System.Action u8 = x8 - y8; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (40,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action u7 = x7 + y7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7 + y7").WithLocation(40, 28), // (45,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action u8 = x8 - y8; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x8 - y8").WithLocation(45, 28) ); } [Fact] public void BinaryOperator_12() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1, CL0 y1) { CL0? u1 = x1 && !y1; } void Test2(bool x2, bool y2) { bool u2 = x2 && !y2; } } class CL0 { public static CL0 operator &(CL0? x, CL0 y) { return new CL0(); } public static bool operator true(CL0? x) { return false; } public static bool operator false(CL0? x) { return false; } public static CL0? operator !(CL0 x) { return null; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,25): warning CS8604: Possible null reference argument for parameter 'y' in 'CL0 CL0.operator &(CL0? x, CL0 y)'. // CL0? u1 = x1 && !y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "!y1").WithArguments("y", "CL0 CL0.operator &(CL0? x, CL0 y)").WithLocation(10, 25) ); } [Fact] public void BinaryOperator_13() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1, CL0 y1) { CL0 z1 = x1 && y1; } } class CL0 { public static CL0? operator &(CL0 x, CL0 y) { return new CL0(); } public static bool operator true(CL0 x) { return false; } public static bool operator false(CL0? x) { return false; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 z1 = x1 && y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1 && y1").WithLocation(10, 18) ); } [Fact] public void BinaryOperator_14() { var source = @"struct S { public static S operator&(S a, S b) => a; public static S operator|(S a, S b) => b; public static bool operator true(S? s) => true; public static bool operator false(S? s) => false; static void And(S x, S? y) { if (x && x) { } if (x && y) { } if (y && x) { } if (y && y) { } } static void Or(S x, S? y) { if (x || x) { } if (x || y) { } if (y || x) { } if (y || y) { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void BinaryOperator_15() { var source = @"struct S { public static S operator+(S a, S b) => a; static void F(S x, S? y) { S? s; s = x + x; s = x + y; s = y + x; s = y + y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void BinaryOperator_15_WithDisallowNull() { var source = @" using System.Diagnostics.CodeAnalysis; struct S { public static S? operator+(S? a, [DisallowNull] S? b) => throw null!; static void F(S? x, S? y) { if (x == null) throw null!; S? s; s = x + x; s = x + y; // 1 s = y + x; s = y + y; // 2 } }"; // Analyze operator call properly (honoring [Disallow|Allow|Maybe|NotNull] attribute annotations) https://github.com/dotnet/roslyn/issues/32671 var comp = CreateCompilation(new[] { source, DisallowNullAttributeDefinition }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void BinaryOperator_16() { var source = @"struct S { public static bool operator<(S a, S b) => true; public static bool operator<=(S a, S b) => true; public static bool operator>(S a, S b) => true; public static bool operator>=(S a, S b) => true; public static bool operator==(S a, S b) => true; public static bool operator!=(S a, S b) => true; public override bool Equals(object other) => true; public override int GetHashCode() => 0; static void F(S x, S? y) { if (x < y) { } if (x <= y) { } if (x > y) { } if (x >= y) { } if (x == y) { } if (x != y) { } if (y < x) { } if (y <= x) { } if (y > x) { } if (y >= x) { } if (y == x) { } if (y != x) { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void MethodGroupConversion_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1) { System.Action u1 = x1.M1; } void Test2(CL0 x2) { System.Action u2 = x2.M1; } } class CL0 { public void M1() {} } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,28): warning CS8602: Dereference of a possibly null reference. // System.Action u1 = x1.M1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(10, 28) ); } [Fact] public void MethodGroupConversion_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void M1(T x){} void Test1() { System.Action u1 = M1; } void Test2() { System.Action u2 = M1; } void Test3() { System.Action> u3 = M1>; } void Test4() { System.Action> u4 = M1>; } } class CL0 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,37): warning CS8622: Nullability of reference types in type of parameter 'x' of 'void C.M1(string x)' doesn't match the target delegate 'Action'. // System.Action u1 = M1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M1").WithArguments("x", "void C.M1(string x)", "System.Action").WithLocation(12, 37), // (22,42): warning CS8622: Nullability of reference types in type of parameter 'x' of 'void C.M1>(CL0 x)' doesn't match the target delegate 'Action>'. // System.Action> u3 = M1>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M1>").WithArguments("x", "void C.M1>(CL0 x)", "System.Action>").WithLocation(22, 42), // (27,41): warning CS8622: Nullability of reference types in type of parameter 'x' of 'void C.M1>(CL0 x)' doesn't match the target delegate 'Action>'. // System.Action> u4 = M1>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "M1>").WithArguments("x", "void C.M1>(CL0 x)", "System.Action>").WithLocation(27, 41) ); } [Fact] public void MethodGroupConversion_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { void M1(T x){} void Test1() { System.Action u1 = (System.Action)M1; // 1 System.Action u2 = (System.Action)M1; System.Action> u3 = (System.Action>)M1>; // 2 System.Action> u4 = (System.Action>)M1>; //3 } } class CL0 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (8,37): warning CS8622: Nullability of reference types in type of parameter 'x' of 'void C.M1(string x)' doesn't match the target delegate 'Action'. // System.Action u1 = (System.Action)M1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(System.Action)M1").WithArguments("x", "void C.M1(string x)", "System.Action").WithLocation(8, 37), // (10,42): warning CS8622: Nullability of reference types in type of parameter 'x' of 'void C.M1>(CL0 x)' doesn't match the target delegate 'Action>'. // System.Action> u3 = (System.Action>)M1>; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(System.Action>)M1>").WithArguments("x", "void C.M1>(CL0 x)", "System.Action>").WithLocation(10, 42), // (11,41): warning CS8622: Nullability of reference types in type of parameter 'x' of 'void C.M1>(CL0 x)' doesn't match the target delegate 'Action>'. // System.Action> u4 = (System.Action>)M1>; //3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(System.Action>)M1>").WithArguments("x", "void C.M1>(CL0 x)", "System.Action>").WithLocation(11, 41) ); } [Fact] public void MethodGroupConversion_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } T M1(){throw new System.Exception();} void Test1() { System.Func u1 = M1; } void Test2() { System.Func u2 = M1; } void Test3() { System.Func> u3 = M1>; } void Test4() { System.Func> u4 = M1>; } } class CL0 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (17,34): warning CS8621: Nullability of reference types in return type of 'string? C.M1()' doesn't match the target delegate 'Func'. // System.Func u2 = M1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M1").WithArguments("string? C.M1()", "System.Func").WithLocation(17, 34), // (22,40): warning CS8621: Nullability of reference types in return type of 'CL0 C.M1>()' doesn't match the target delegate 'Func>'. // System.Func> u3 = M1>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M1>").WithArguments("CL0 C.M1>()", "System.Func>").WithLocation(22, 40), // (27,39): warning CS8621: Nullability of reference types in return type of 'CL0 C.M1>()' doesn't match the target delegate 'Func>'. // System.Func> u4 = M1>; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "M1>").WithArguments("CL0 C.M1>()", "System.Func>").WithLocation(27, 39) ); } [Fact] public void MethodGroupConversion_05() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } T M1(){throw new System.Exception();} void Test1() { System.Func u1 = (System.Func)M1; System.Func u2 = (System.Func)M1; // 1 System.Func> u3 = (System.Func>)M1>; // 2 System.Func> u4 = (System.Func>)M1>; // 3 } } class CL0 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,34): warning CS8621: Nullability of reference types in return type of 'string? C.M1()' doesn't match the target delegate 'Func'. // System.Func u2 = (System.Func)M1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "(System.Func)M1").WithArguments("string? C.M1()", "System.Func").WithLocation(13, 34), // (14,40): warning CS8621: Nullability of reference types in return type of 'CL0 C.M1>()' doesn't match the target delegate 'Func>'. // System.Func> u3 = (System.Func>)M1>; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "(System.Func>)M1>").WithArguments("CL0 C.M1>()", "System.Func>").WithLocation(14, 40), // (15,39): warning CS8621: Nullability of reference types in return type of 'CL0 C.M1>()' doesn't match the target delegate 'Func>'. // System.Func> u4 = (System.Func>)M1>; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "(System.Func>)M1>").WithArguments("CL0 C.M1>()", "System.Func>").WithLocation(15, 39) ); } [Fact] public void MethodGroupConversion_06() { var source = @"delegate void D(T t); class A { } class B { internal void F(T t) { } } class C { static B Create(T t) => new B(); static void F1(A x, A? y) { D d1; d1 = Create(x).F; d1 = Create(y).F; x = y; // 1 d1 = Create(x).F; } static void F2(A x, A? y) { D d2; d2 = Create(x).F; // 2 d2 = Create(y).F; x = y; // 3 d2 = Create(x).F; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = y; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(15, 13), // (21,14): warning CS8622: Nullability of reference types in type of parameter 't' of 'void B.F(A t)' doesn't match the target delegate 'D'. // d2 = Create(x).F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "Create(x).F").WithArguments("t", "void B.F(A t)", "D").WithLocation(21, 14), // (23,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = y; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(23, 13)); } [Fact] public void UnaryOperator_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1) { CL0 u1 = !x1; } void Test2(CL1 x2) { CL1 u2 = !x2; } void Test3(CL2? x3) { CL2 u3 = !x3; } void Test4(CL1 x4) { dynamic y4 = x4; CL1 u4 = !y4; dynamic v4 = !y4 ?? y4; } void Test5(bool x5) { bool u5 = !x5; } } class CL0 { public static CL0 operator !(CL0 x) { return new CL0(); } } class CL1 { public static CL1? operator !(CL1 x) { return new CL1(); } } class CL2 { public static CL2 operator !(CL2? x) { return new CL2(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator !(CL0 x)'. // CL0 u1 = !x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator !(CL0 x)").WithLocation(10, 19), // (15,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u2 = !x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "!x2").WithLocation(15, 18) ); } [Fact] public void UnaryOperator_02() { var source = @"struct S { public static S operator~(S s) => s; static void F(S? s) { s = ~s; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Conversion_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1) { CL1 u1 = x1; } void Test2(CL0? x2, CL0 y2) { int u2 = x2; long v2 = x2; int w2 = y2; } void Test3(CL0 x3) { CL2 u3 = x3; } void Test4(CL0 x4) { CL3? u4 = x4; CL3 v4 = u4 ?? new CL3(); } void Test5(dynamic? x5) { CL3 u5 = x5; } void Test6(dynamic? x6) { CL3? u6 = x6; CL3 v6 = u6 ?? new CL3(); } void Test7(CL0? x7) { dynamic u7 = x7; } void Test8(CL0 x8) { dynamic? u8 = x8; dynamic v8 = u8 ?? x8; } void Test9(dynamic? x9) { object u9 = x9; } void Test10(object? x10) { dynamic u10 = x10; } void Test11(CL4? x11) { CL3 u11 = x11; } void Test12(CL3? x12) { CL4 u12 = (CL4)x12; } void Test13(int x13) { object? u13 = x13; object v13 = u13 ?? new object(); } void Test14(T x14) { object u14 = x14; object v14 = ((object)x14) ?? new object(); } void Test15(int? x15) { object u15 = x15; } void Test16() { System.IFormattable? u16 = $""{3}""; object v16 = u16 ?? new object(); } } class CL0 { public static implicit operator CL1(CL0 x) { return new CL1(); } public static implicit operator int(CL0 x) { return 0; } public static implicit operator long(CL0? x) { return 0; } public static implicit operator CL2?(CL0 x) { return new CL2(); } public static implicit operator CL3(CL0? x) { return new CL3(); } } class CL1 {} class CL2 {} class CL3 {} class CL4 : CL3 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0.implicit operator CL1(CL0 x)'. // CL1 u1 = x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0.implicit operator CL1(CL0 x)").WithLocation(10, 18), // (15,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0.implicit operator int(CL0 x)'. // int u2 = x2; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL0.implicit operator int(CL0 x)").WithLocation(15, 18), // (22,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL2 u3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(22, 18), // (33,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL3 u5 = x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5").WithLocation(33, 18), // (44,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic u7 = x7; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7").WithLocation(44, 22), // (55,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object u9 = x9; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x9").WithLocation(55, 21), // (60,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic u10 = x10; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x10").WithLocation(60, 23), // (65,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL3 u11 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(65, 19), // (70,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL4 u12 = (CL4)x12; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(CL4)x12").WithLocation(70, 19), // (81,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object u14 = x14; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x14").WithLocation(81, 22), // (82,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // object v14 = ((object)x14) ?? new object(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x14").WithLocation(82, 23), // (87,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // object u15 = x15; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x15").WithLocation(87, 22)); } [Fact] public void Conversion_02() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0 x1) { CL0 u1 = x1; CL0 v1 = (CL0)x1; } } class CL0 { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,26): warning CS8619: Nullability of reference types in value of type 'CL0' doesn't match target type 'CL0'. // CL0 u1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("CL0", "CL0").WithLocation(10, 26), // (11,26): warning CS8619: Nullability of reference types in value of type 'CL0' doesn't match target type 'CL0'. // CL0 v1 = (CL0)x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(CL0)x1").WithArguments("CL0", "CL0").WithLocation(11, 26) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void ImplicitConversions_01() { var source = @"class A { } class B : A { } class C { static void F1(B x1) { A y1 = x1; y1 = x1; y1 = x1!; } static void F2(B x2) { A y2 = x2; y2 = x2; y2 = x2!; } static void F3(B? x3) { A y3 = x3; y3 = x3; y3 = x3!; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,25): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // A y1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("B", "A").WithLocation(7, 25), // (8,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // y1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("B", "A").WithLocation(8, 14), // (13,24): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // A y2 = x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("B", "A").WithLocation(13, 24), // (14,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // y2 = x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("B", "A").WithLocation(14, 14), // (19,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // A y3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(19, 25), // (19,25): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // A y3 = x3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("B", "A").WithLocation(19, 25), // (20,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(20, 14), // (20,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // y3 = x3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("B", "A").WithLocation(20, 14) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void ImplicitConversions_02() { var source = @"interface IA { } interface IB : IA { } class C { static void F1(IB x1) { IA y1 = x1; y1 = x1; y1 = x1!; } static void F2(IB x2) { IA y2 = x2; y2 = x2; y2 = x2!; } static void F3(IB? x3) { IA y3 = x3; y3 = x3; y3 = x3!; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,26): warning CS8619: Nullability of reference types in value of type 'IB' doesn't match target type 'IA'. // IA y1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("IB", "IA").WithLocation(7, 26), // (8,14): warning CS8619: Nullability of reference types in value of type 'IB' doesn't match target type 'IA'. // y1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("IB", "IA").WithLocation(8, 14), // (13,25): warning CS8619: Nullability of reference types in value of type 'IB' doesn't match target type 'IA'. // IA y2 = x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("IB", "IA").WithLocation(13, 25), // (14,14): warning CS8619: Nullability of reference types in value of type 'IB' doesn't match target type 'IA'. // y2 = x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("IB", "IA").WithLocation(14, 14), // (19,26): warning CS8600: Converting null literal or possible null value to non-nullable type. // IA y3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(19, 26), // (19,26): warning CS8619: Nullability of reference types in value of type 'IB' doesn't match target type 'IA'. // IA y3 = x3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("IB", "IA").WithLocation(19, 26), // (20,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(20, 14), // (20,14): warning CS8619: Nullability of reference types in value of type 'IB' doesn't match target type 'IA'. // y3 = x3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("IB", "IA").WithLocation(20, 14)); } [Fact] public void ImplicitConversions_03() { var source = @"interface IOut { } class C { static void F(IOut x) { IOut y = x; } static void G(IOut x) { IOut y = x; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,26): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // IOut y = x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IOut", "IOut").WithLocation(10, 26)); } [Fact] public void ImplicitConversions_04() { var source = @"interface IIn { } class C { static void F(IIn x) { IIn y = x; } static void G(IIn x) { IIn y = x; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,26): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // IIn y = x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("IIn", "IIn").WithLocation(6, 26)); } [Fact] public void ImplicitConversions_05() { var source = @"interface IOut { } class A : IOut { } class C { static void F(A x) { IOut y = x; } static void G(A x) { IOut y = x; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,26): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'IOut'. // IOut y = x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "IOut").WithLocation(11, 26)); } [Fact] public void ImplicitConversions_06() { var source = @"interface IIn { } interface IOut { } class A : IIn, IOut { } class B : IIn, IOut { } class C { static void F(A a1, B b1) { IIn y = a1; y = b1; IOut z = a1; z = b1; } static void G(A a2, B b2) { IIn y = a2; y = b2; IOut z = a2; z = b2; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29897: Report the base types that did not match // rather than the derived or implementing type. For instance, report `'IIn' // doesn't match ... 'IIn'` rather than `'A' doesn't match ...`. comp.VerifyDiagnostics( // (9,26): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'IIn'. // IIn y = a1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a1").WithArguments("A", "IIn").WithLocation(9, 26), // (10,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // y = b1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b1").WithArguments("B", "IIn").WithLocation(10, 13), // (18,26): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'IOut'. // IOut z = a2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("A", "IOut").WithLocation(18, 26), // (19,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IOut'. // z = b2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b2").WithArguments("B", "IOut").WithLocation(19, 13)); } [Fact] public void ImplicitConversions_07() { var source = @"class A { } class B { public static implicit operator A(B b) => throw null!; } class C { static B F(T t) => throw null!; static void G(A a) => throw null!; static void Main(object? x) { var y = F(x); G(y); if (x == null) return; var z = F(x); G(z); // warning } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29898: Report warning for `G(z)`? comp.VerifyDiagnostics(); } [Fact] public void IdentityConversion_LocalDeclaration() { var source = @"interface I { } interface IIn { } interface IOut { } interface IBoth { } class C { static void F1(I x1, IIn y1, IOut z1, IBoth w1) { I a1 = x1; IIn b1 = y1; IOut c1 = z1; IBoth d1 = w1; } static void F2(I x2, IIn y2, IOut z2, IBoth w2) { I a2 = x2; IIn b2 = y2; IOut c2 = z2; IBoth d2 = w2; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,25): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // I a1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I", "I").WithLocation(9, 25), // (10,27): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // IIn b1 = y1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(10, 27), // (12,38): warning CS8619: Nullability of reference types in value of type 'IBoth' doesn't match target type 'IBoth'. // IBoth d1 = w1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w1").WithArguments("IBoth", "IBoth").WithLocation(12, 38), // (16,24): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // I a2 = x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("I", "I").WithLocation(16, 24), // (18,27): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // IOut c2 = z2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z2").WithArguments("IOut", "IOut").WithLocation(18, 27), // (19,36): warning CS8619: Nullability of reference types in value of type 'IBoth' doesn't match target type 'IBoth'. // IBoth d2 = w2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w2").WithArguments("IBoth", "IBoth").WithLocation(19, 36)); } [Fact] public void IdentityConversion_Assignment() { var source = @"interface I { } interface IIn { } interface IOut { } interface IBoth { } class C { static void F1(I x1, IIn y1, IOut z1, IBoth w1) { I a1; a1 = x1; IIn b1; b1 = y1; IOut c1; c1 = z1; IBoth d1; d1 = w1; } static void F2(I x2, IIn y2, IOut z2, IBoth w2) { I a2; a2 = x2; IIn b2; b2 = y2; IOut c2; c2 = z2; IBoth d2; d2 = w2; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,14): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // a1 = x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("I", "I").WithLocation(10, 14), // (12,14): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // b1 = y1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y1").WithArguments("IIn", "IIn").WithLocation(12, 14), // (16,14): warning CS8619: Nullability of reference types in value of type 'IBoth' doesn't match target type 'IBoth'. // d1 = w1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w1").WithArguments("IBoth", "IBoth").WithLocation(16, 14), // (21,14): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // a2 = x2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("I", "I").WithLocation(21, 14), // (25,14): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // c2 = z2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z2").WithArguments("IOut", "IOut").WithLocation(25, 14), // (27,14): warning CS8619: Nullability of reference types in value of type 'IBoth' doesn't match target type 'IBoth'. // d2 = w2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w2").WithArguments("IBoth", "IBoth").WithLocation(27, 14)); } [Fact] public void IdentityConversion_Argument() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(I x, IIn y, IOut z) { G(x, y, z); } static void G(I x, IIn y, IOut z) { F(x, y, z); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.G(I x, IIn y, IOut z)'. // G(x, y, z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.G(I x, IIn y, IOut z)").WithLocation(8, 11), // (8,14): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'void C.G(I x, IIn y, IOut z)'. // G(x, y, z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn", "IIn", "y", "void C.G(I x, IIn y, IOut z)").WithLocation(8, 14), // (12,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.F(I x, IIn y, IOut z)'. // F(x, y, z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.F(I x, IIn y, IOut z)").WithLocation(12, 11), // (12,17): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'z' in 'void C.F(I x, IIn y, IOut z)'. // F(x, y, z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut", "IOut", "z", "void C.F(I x, IIn y, IOut z)").WithLocation(12, 17)); } [Fact] public void IdentityConversion_OutArgument() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(out I x, out IIn y, out IOut z) { G(out x, out y, out z); } static void G(out I x, out IIn y, out IOut z) { F(out x, out y, out z); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,15): warning CS8624: Argument of type 'I' cannot be used as an output of type 'I' for parameter 'x' in 'void C.G(out I x, out IIn y, out IOut z)' due to differences in the nullability of reference types. // G(out x, out y, out z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x").WithArguments("I", "I", "x", "void C.G(out I x, out IIn y, out IOut z)").WithLocation(8, 15), // (8,29): warning CS8624: Argument of type 'IOut' cannot be used as an output of type 'IOut' for parameter 'z' in 'void C.G(out I x, out IIn y, out IOut z)' due to differences in the nullability of reference types. // G(out x, out y, out z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "z").WithArguments("IOut", "IOut", "z", "void C.G(out I x, out IIn y, out IOut z)").WithLocation(8, 29), // (12,15): warning CS8624: Argument of type 'I' cannot be used as an output of type 'I' for parameter 'x' in 'void C.F(out I x, out IIn y, out IOut z)' due to differences in the nullability of reference types. // F(out x, out y, out z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "x").WithArguments("I", "I", "x", "void C.F(out I x, out IIn y, out IOut z)").WithLocation(12, 15), // (12,22): warning CS8624: Argument of type 'IIn' cannot be used as an output of type 'IIn' for parameter 'y' in 'void C.F(out I x, out IIn y, out IOut z)' due to differences in the nullability of reference types. // F(out x, out y, out z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "y").WithArguments("IIn", "IIn", "y", "void C.F(out I x, out IIn y, out IOut z)").WithLocation(12, 22) ); } [Fact] public void IdentityConversion_RefArgument() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(ref I x, ref IIn y, ref IOut z) { G(ref x, ref y, ref z); } static void G(ref I x, ref IIn y, ref IOut z) { F(ref x, ref y, ref z); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,15): warning CS8620: Argument of type 'I' cannot be used as an input of type 'I' for parameter 'x' in 'void C.G(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // G(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.G(ref I x, ref IIn y, ref IOut z)").WithLocation(8, 15), // (8,22): warning CS8620: Argument of type 'IIn' cannot be used as an input of type 'IIn' for parameter 'y' in 'void C.G(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // G(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn", "IIn", "y", "void C.G(ref I x, ref IIn y, ref IOut z)").WithLocation(8, 22), // (8,29): warning CS8620: Argument of type 'IOut' cannot be used as an input of type 'IOut' for parameter 'z' in 'void C.G(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // G(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut", "IOut", "z", "void C.G(ref I x, ref IIn y, ref IOut z)").WithLocation(8, 29), // (12,15): warning CS8620: Argument of type 'I' cannot be used as an input of type 'I' for parameter 'x' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // F(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 15), // (12,22): warning CS8620: Argument of type 'IIn' cannot be used as an input of type 'IIn' for parameter 'y' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // F(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn", "IIn", "y", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 22), // (12,29): warning CS8620: Argument of type 'IOut' cannot be used as an input of type 'IOut' for parameter 'z' in 'void C.F(ref I x, ref IIn y, ref IOut z)' due to differences in the nullability of reference types. // F(ref x, ref y, ref z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut", "IOut", "z", "void C.F(ref I x, ref IIn y, ref IOut z)").WithLocation(12, 29)); } [Fact] public void IdentityConversion_InArgument() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static void F(in I x, in IIn y, in IOut z) { G(in x, in y, in z); } static void G(in I x, in IIn y, in IOut z) { F(in x, in y, in z); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.G(in I x, in IIn y, in IOut z)'. // G(in x, in y, in z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.G(in I x, in IIn y, in IOut z)").WithLocation(8, 14), // (8,20): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'void C.G(in I x, in IIn y, in IOut z)'. // G(in x, in y, in z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn", "IIn", "y", "void C.G(in I x, in IIn y, in IOut z)").WithLocation(8, 20), // (12,14): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'void C.F(in I x, in IIn y, in IOut z)'. // F(in x, in y, in z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.F(in I x, in IIn y, in IOut z)").WithLocation(12, 14), // (12,26): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'z' in 'void C.F(in I x, in IIn y, in IOut z)'. // F(in x, in y, in z); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut", "IOut", "z", "void C.F(in I x, in IIn y, in IOut z)").WithLocation(12, 26)); } [Fact] public void IdentityConversion_ExtensionThis() { var source = @"interface I { } interface IIn { } interface IOut { } static class E { static void F1(object x, object? y) { x.F1A(); y.F1A(); x.F1B(); y.F1B(); // 1 } static void F1A(this object? o) { } static void F1B(this object o) { } static void F2(I x, I y) { x.F2A(); // 2 y.F2A(); x.F2B(); y.F2B(); // 3 } static void F2A(this I o) { } static void F2B(this I o) { } static void F3(IIn x, IIn y) { x.F3A(); // 4 y.F3A(); x.F3B(); y.F3B(); } static void F3A(this IIn o) { } static void F3B(this IIn o) { } static void F4(IOut x, IOut y) { x.F4A(); y.F4A(); x.F4B(); y.F4B(); // 5 } static void F4A(this IOut o) { } static void F4B(this IOut o) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8604: Possible null reference argument for parameter 'o' in 'void E.F1B(object o)'. // y.F1B(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("o", "void E.F1B(object o)").WithLocation(11, 9), // (17,9): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'o' in 'void E.F2A(I o)'. // x.F2A(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "o", "void E.F2A(I o)").WithLocation(17, 9), // (20,9): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'o' in 'void E.F2B(I o)'. // y.F2B(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "o", "void E.F2B(I o)").WithLocation(20, 9), // (26,9): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'o' in 'void E.F3A(IIn o)'. // x.F3A(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IIn", "IIn", "o", "void E.F3A(IIn o)").WithLocation(26, 9), // (38,9): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'o' in 'void E.F4B(IOut o)'. // y.F4B(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IOut", "IOut", "o", "void E.F4B(IOut o)").WithLocation(38, 9)); } // https://github.com/dotnet/roslyn/issues/29899: Clone this method using types from unannotated assemblies // rather than `x!`, particularly because `x!` results in IsNullable=false rather than IsNullable=null. [Fact] public void IdentityConversion_TypeInference_IsNullableNull() { var source = @"class A { } class B { static T F1(T x, T y) { return x; } static void G1(object? x, object y) { F1(x, x!).ToString(); F1(x!, x).ToString(); F1(y, y!).ToString(); F1(y!, y).ToString(); } static T F2(A x, A y) { throw new System.Exception(); } static void G(A z, A w) { F2(z, z!).ToString(); F2(z!, z).ToString(); F2(w, w!).ToString(); F2(w!, w).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // F1(x, x!).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x, x!)").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // F1(x!, x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x!, x)").WithLocation(13, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // F2(z, z!).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(z, z!)").WithLocation(23, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // F2(z!, z).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(z!, z)").WithLocation(24, 9)); } [Fact] public void IdentityConversion_IndexerArgumentsOrder() { var source = @"interface I { } class C { static object F(C c, I x, I y) { return c[ y: y, // warn 1 x: x]; } static object G(C c, I x, I y) { return c[ y: y, x: x]; // warn 2 } object this[I x, I y] => new object(); }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,16): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'object C.this[I x, I y]'. // y: y, // warn 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "y", "object C.this[I x, I y]").WithLocation(7, 16), // (14,16): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'object C.this[I x, I y]'. // x: x]; // warn 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "object C.this[I x, I y]").WithLocation(14, 16)); } [Fact] public void IncrementOperator_01() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(CL0? x1) { CL0? u1 = ++x1; CL0 v1 = u1 ?? new CL0(); CL0 w1 = x1 ?? new CL0(); } void Test2(CL0? x2) { CL0 u2 = x2++; CL0 v2 = x2 ?? new CL0(); } void Test3(CL1? x3) { CL1 u3 = --x3; CL1 v3 = x3; } void Test4(CL1 x4) { CL1? u4 = x4--; // Result of increment is nullable, storing it in not nullable parameter. CL1 v4 = u4 ?? new CL1(); CL1 w4 = x4 ?? new CL1(); } void Test5(CL1 x5) { CL1 u5 = --x5; } void Test6(CL1 x6) { x6--; } void Test7() { CL1 x7; x7--; } } class CL0 { public static CL0 operator ++(CL0 x) { return new CL0(); } } class CL1 { public static CL1? operator --(CL1? x) { return new CL1(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,21): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(10, 21), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(16, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2++").WithLocation(16, 18), // (21,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u3 = --x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3").WithLocation(21, 18), // (22,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 v3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(22, 18), // (26,19): warning CS8601: Possible null reference assignment. // CL1? u4 = x4--; // Result of increment is nullable, storing it in not nullable parameter. Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4--").WithLocation(26, 19), // (32,18): warning CS8601: Possible null reference assignment. // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x5").WithLocation(32, 18), // (32,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x5").WithLocation(32, 18), // (37,9): warning CS8601: Possible null reference assignment. // x6--; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x6--").WithLocation(37, 9), // (43,9): error CS0165: Use of unassigned local variable 'x7' // x7--; Diagnostic(ErrorCode.ERR_UseDefViolation, "x7").WithArguments("x7").WithLocation(43, 9), // (43,9): warning CS8601: Possible null reference assignment. // x7--; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x7--").WithLocation(43, 9) ); } [Fact] public void IncrementOperator_02() { CSharpCompilation c = CreateCompilation( new[] { @"#pragma warning disable 8618 class C { static void Main() { } void Test1() { CL0? u1 = ++x1; CL0 v1 = u1 ?? new CL0(); } void Test2() { CL0 u2 = x2++; } void Test3() { CL1 u3 = --x3; } void Test4() { CL1? u4 = x4--; // Result of increment is nullable, storing it in not nullable property. CL1 v4 = u4 ?? new CL1(); } void Test5(CL1 x5) { CL1 u5 = --x5; } CL0? x1 {get; set;} CL0? x2 {get; set;} CL1? x3 {get; set;} CL1 x4 {get; set;} CL1 x5 {get; set;} } class CL0 { public static CL0 operator ++(CL0 x) { return new CL0(); } } class CL1 { public static CL1? operator --(CL1? x) { return new CL1(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,21): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(10, 21), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(16, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 u2 = x2++; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2++").WithLocation(16, 18), // (21,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u3 = --x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3").WithLocation(21, 18), // (26,19): warning CS8601: Possible null reference assignment. // CL1? u4 = x4--; // Result of increment is nullable, storing it in not nullable property. Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4--").WithLocation(26, 19), // (32,18): warning CS8601: Possible null reference assignment. // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x5").WithLocation(32, 18), // (32,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u5 = --x5; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x5").WithLocation(32, 18) ); } [Fact] public void IncrementOperator_03() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(X1 x1) { CL0? u1 = ++x1[0]; CL0 v1 = u1 ?? new CL0(); } void Test2(X1 x2) { CL0 u2 = x2[0]++; } void Test3(X3 x3) { CL1 u3 = --x3[0]; } void Test4(X4 x4) { CL1? u4 = x4[0]--; // Result of increment is nullable, storing it in not nullable parameter. CL1 v4 = u4 ?? new CL1(); } void Test5(X4 x5) { CL1 u5 = --x5[0]; } } class CL0 { public static CL0 operator ++(CL0 x) { return new CL0(); } } class CL1 { public static CL1? operator --(CL1? x) { return new CL1(); } } class X1 { public CL0? this[int x] { get { return null; } set { } } } class X3 { public CL1? this[int x] { get { return null; } set { } } } class X4 { public CL1 this[int x] { get { return new CL1(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,21): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0? u1 = ++x1[0]; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1[0]").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(10, 21), // (16,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL0 CL0.operator ++(CL0 x)'. // CL0 u2 = x2[0]++; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2[0]").WithArguments("x", "CL0 CL0.operator ++(CL0 x)").WithLocation(16, 18), // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 u2 = x2[0]++; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2[0]++").WithLocation(16, 18), // (21,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u3 = --x3[0]; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3[0]").WithLocation(21, 18), // (26,19): warning CS8601: Possible null reference assignment. // CL1? u4 = x4[0]--; // Result of increment is nullable, storing it in not nullable parameter. Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4[0]--").WithLocation(26, 19), // (32,18): warning CS8601: Possible null reference assignment. // CL1 u5 = --x5[0]; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "--x5[0]").WithLocation(32, 18), // (32,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u5 = --x5[0]; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x5[0]").WithLocation(32, 18) ); } [Fact] public void IncrementOperator_04() { CSharpCompilation c = CreateCompilation(new[] { @" class C { static void Main() { } void Test1(dynamic? x1) { dynamic? u1 = ++x1; dynamic v1 = u1 ?? new object(); } void Test2(dynamic? x2) { dynamic u2 = x2++; } void Test3(dynamic? x3) { dynamic u3 = --x3; } void Test4(dynamic x4) { dynamic? u4 = x4--; dynamic v4 = u4 ?? new object(); } void Test5(dynamic x5) { dynamic u5 = --x5; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (16,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic u2 = x2++; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2++").WithLocation(16, 22), // (21,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic u3 = --x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "--x3").WithLocation(21, 22) ); } [Fact] public void IncrementOperator_05() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(B? x1) { B? u1 = ++x1; B v1 = u1 ?? new B(); } } class A { public static C? operator ++(A x) { return new C(); } } class C : A { public static implicit operator B(C x) { return new B(); } } class B : A { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'C? A.operator ++(A x)'. // B? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "C? A.operator ++(A x)").WithLocation(10, 19), // (10,17): warning CS8604: Possible null reference argument for parameter 'x' in 'C.implicit operator B(C x)'. // B? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "++x1").WithArguments("x", "C.implicit operator B(C x)").WithLocation(10, 17) ); } [Fact] public void IncrementOperator_06() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(B x1) { B u1 = ++x1; } } class A { public static C operator ++(A x) { return new C(); } } class C : A { public static implicit operator B?(C x) { return new B(); } } class B : A { } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,16): warning CS8601: Possible null reference assignment. // B u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "++x1").WithLocation(10, 16), // (10,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // B u1 = ++x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "++x1").WithLocation(10, 16) ); } [Fact] public void IncrementOperator_07() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(Convertible? x1) { Convertible? u1 = ++x1; Convertible v1 = u1 ?? new Convertible(); } void Test2(int? x2) { var u2 = ++x2; } void Test3(byte x3) { var u3 = ++x3; } } class Convertible { public static implicit operator int(Convertible c) { return 0; } public static implicit operator Convertible(int i) { return new Convertible(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,29): warning CS8604: Possible null reference argument for parameter 'c' in 'Convertible.implicit operator int(Convertible c)'. // Convertible? u1 = ++x1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("c", "Convertible.implicit operator int(Convertible c)").WithLocation(10, 29) ); } [Fact] public void CompoundAssignment_01() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL1? x1, CL0 y1) { CL1? u1 = x1 += y1; // 1, 2 CL1 v1 = u1 ?? new CL1(); CL1 w1 = x1 ?? new CL1(); } } class CL0 { public static CL1 operator +(CL0 x, CL0 y) { return new CL1(); } } class CL1 { public static implicit operator CL0(CL1 x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1 += y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. // CL1? u1 = x1 += y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 19) ); } [Fact] public void CompoundAssignment_02() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL1? x1, CL0? y1) { CL1? u1 = x1 += y1; // 1, 2 CL1 v1 = u1 ?? new CL1(); CL1 w1 = x1 ?? new CL1(); } } class CL0 { public static CL1 operator +(CL0 x, CL0 y) { return new CL1(); } } class CL1 { public static implicit operator CL0(CL1? x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. // CL1? u1 = x1 += y1; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 19), // (10,25): warning CS8604: Possible null reference argument for parameter 'y' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. // CL1? u1 = x1 += y1; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y1").WithArguments("y", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 25) ); } [Fact] public void CompoundAssignment_03() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL1? x1, CL0? y1) { CL1? u1 = x1 += y1; CL1 v1 = u1 ?? new CL1(); CL1 w1 = x1 ?? new CL1(); } void Test2(CL0? x2, CL0 y2) { CL0 u2 = x2 += y2; CL0 w2 = x2; } void Test3(CL0? x3, CL0 y3) { x3 = new CL0(); CL0 u3 = x3 += y3; CL0 w3 = x3; } void Test4(CL0? x4, CL0 y4) { x4 = new CL0(); x4 += y4; CL0 w4 = x4; } } class CL0 { public static CL1 operator +(CL0 x, CL0? y) { return new CL1(); } } class CL1 { public static implicit operator CL0?(CL1? x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0? y)'. // CL1? u1 = x1 += y1; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0? y)").WithLocation(10, 19), // (17,18): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0? y)'. // CL0 u2 = x2 += y2; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0? y)").WithLocation(17, 18), // (17,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 u2 = x2 += y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2 += y2").WithLocation(17, 18), // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 w2 = x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(18, 18), // (24,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 u3 = x3 += y3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 += y3").WithLocation(24, 18), // (25,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 w3 = x3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(25, 18), // (32,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL0 w4 = x4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x4").WithLocation(32, 18) ); } [Fact] public void CompoundAssignment_04() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL1? x1, CL0? y1) { x1 = new CL1(); CL1? u1 = x1 += y1; CL1 w1 = x1; w1 = u1; } void Test2(CL1 x2, CL0 y2) { CL1 u2 = x2 += y2; CL1 w2 = x2; } void Test3(CL1 x3, CL0 y3) { x3 += y3; } void Test4(CL0? x4, CL0 y4) { CL0? u4 = x4 += y4; CL0 v4 = u4 ?? new CL0(); CL0 w4 = x4 ?? new CL0(); } void Test5(CL0 x5, CL0 y5) { x5 += y5; } void Test6(CL0 y6) { CL1 x6; x6 += y6; } } class CL0 { public static CL1? operator +(CL0 x, CL0? y) { return new CL1(); } } class CL1 { public static implicit operator CL0(CL1 x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 w1 = x1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(12, 18), // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // w1 = u1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u1").WithLocation(13, 14), // (18,18): warning CS8601: Possible null reference assignment. // CL1 u2 = x2 += y2; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x2 += y2").WithLocation(18, 18), // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 u2 = x2 += y2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2 += y2").WithLocation(18, 18), // (19,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 w2 = x2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(19, 18), // (24,9): warning CS8601: Possible null reference assignment. // x3 += y3; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x3 += y3").WithLocation(24, 9), // (29,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1? CL0.operator +(CL0 x, CL0? y)'. // CL0? u4 = x4 += y4; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("x", "CL1? CL0.operator +(CL0 x, CL0? y)").WithLocation(29, 19), // (29,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL0? u4 = x4 += y4; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4 += y4").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(29, 19), // (36,9): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // x5 += y5; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x5 += y5").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(36, 9), // (42,9): error CS0165: Use of unassigned local variable 'x6' // x6 += y6; Diagnostic(ErrorCode.ERR_UseDefViolation, "x6").WithArguments("x6").WithLocation(42, 9), // (42,9): warning CS8601: Possible null reference assignment. // x6 += y6; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x6 += y6").WithLocation(42, 9)); } [Fact] public void CompoundAssignment_05() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(int x1, int y1) { var u1 = x1 += y1; } void Test2(int? x2, int y2) { var u2 = x2 += y2; } void Test3(dynamic? x3, dynamic? y3) { dynamic? u3 = x3 += y3; dynamic v3 = u3; dynamic w3 = u3 ?? v3; } void Test4(dynamic? x4, dynamic? y4) { dynamic u4 = x4 += y4; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } [Fact] public void CompoundAssignment_06() { CSharpCompilation c = CreateCompilation( new[] { @"#pragma warning disable 8618 class Test { static void Main() { } void Test1(CL0 y1) { CL1? u1 = x1 += y1; // 1, 2 CL1 v1 = u1 ?? new CL1(); CL1 w1 = x1 ?? new CL1(); } void Test2(CL0 y2) { CL1? u2 = x2 += y2; CL1 v2 = u2 ?? new CL1(); CL1 w2 = x2 ?? new CL1(); } CL1? x1 {get; set;} CL1 x2 {get; set;} } class CL0 { public static CL1 operator +(CL0 x, CL0 y) { return new CL1(); } } class CL1 { public static implicit operator CL0(CL1 x) { return new CL0(); } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1 += y1; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. // CL1? u1 = x1 += y1; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 19) ); } [Fact] public void CompoundAssignment_07() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL2 x1, CL0 y1) { CL1? u1 = x1[0] += y1; // 1, 2 CL1 v1 = u1 ?? new CL1(); CL1 w1 = x1[0] ?? new CL1(); } void Test2(CL3 x2, CL0 y2) { CL1? u2 = x2[0] += y2; CL1 v2 = u2 ?? new CL1(); CL1 w2 = x2[0] ?? new CL1(); } } class CL0 { public static CL1 operator +(CL0 x, CL0 y) { return new CL1(); } } class CL1 { public static implicit operator CL0(CL1 x) { return new CL0(); } } class CL2 { public CL1? this[int x] { get { return new CL1(); } set { } } } class CL3 { public CL1 this[int x] { get { return new CL1(); } set { } } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1[0] += y1; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1[0]").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. // CL1? u1 = x1[0] += y1; // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1[0]").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 19) ); } [Fact] public void IdentityConversion_CompoundAssignment() { var source = @"interface I { } interface IIn { } interface IOut { } class C { public static I operator+(I x, C y) => x; public static IIn operator+(IIn x, C y) => x; public static IOut operator+(IOut x, C y) => x; static void F(C c, I x, I y) { x += c; y += c; // 1, 2, 3 } static void F(C c, IIn x, IIn y) { x += c; y += c; // 4 } static void F(C c, IOut x, IOut y) { x += c; y += c; // 5, 6 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // y += c; // 1, 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I", "I").WithLocation(12, 9), // (12,9): warning CS8620: Argument of type 'I' cannot be used for parameter 'x' of type 'I' in 'I C.operator +(I x, C y)' due to differences in the nullability of reference types. // y += c; // 1, 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("I", "I", "x", "I C.operator +(I x, C y)").WithLocation(12, 9), // (12,9): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // y += c; // 1, 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y += c").WithArguments("I", "I").WithLocation(12, 9), // (17,9): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // y += c; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y += c").WithArguments("IIn", "IIn").WithLocation(17, 9), // (22,9): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // y += c; // 5, 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("IOut", "IOut").WithLocation(22, 9), // (22,9): warning CS8620: Argument of type 'IOut' cannot be used for parameter 'x' of type 'IOut' in 'IOut C.operator +(IOut x, C y)' due to differences in the nullability of reference types. // y += c; // 5, 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IOut", "IOut", "x", "IOut C.operator +(IOut x, C y)").WithLocation(22, 9) ); } [Fact] public void Events_01() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } event System.Action? E1; void Test1() { E1(); } delegate void D2 (object x); event D2 E2; void Test2() { E2(null); } delegate object? D3 (); event D3 E3; void Test3() { object x3 = E3(); } void Test4() { //E1?(); System.Action? x4 = E1; //x4?(); } void Test5() { System.Action x5 = E1; } void Test6(D2? x6) { E2 = x6; } void Test7(D2? x7) { E2 += x7; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // E1(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "E1").WithLocation(12, 9), // (20,12): warning CS8625: Cannot convert null literal to non-nullable reference type. // E2(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(20, 12), // (28,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x3 = E3(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E3()").WithLocation(28, 21), // (40,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action x5 = E1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E1").WithLocation(40, 28), // (45,14): warning CS8601: Possible null reference assignment. // E2 = x6; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x6").WithLocation(45, 14) ); } // https://github.com/dotnet/roslyn/issues/29901: Events are not tracked for structs. // (This should be fixed if/when struct member state is populated lazily.) [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29901")] [WorkItem(29901, "https://github.com/dotnet/roslyn/issues/29901")] public void Events_02() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } } struct TS1 { event System.Action? E1; TS1(System.Action x1) { E1 = x1; System.Action y1 = E1 ?? x1; E1 = x1; TS1 z1 = this; y1 = z1.E1 ?? x1; } void Test3(System.Action x3) { TS1 s3; s3.E1 = x3; System.Action y3 = s3.E1 ?? x3; s3.E1 = x3; TS1 z3 = s3; y3 = z3.E1 ?? x3; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( ); } // https://github.com/dotnet/roslyn/issues/29901: Events are not tracked for structs. // (This should be fixed if/when struct member state is populated lazily.) [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29901")] [WorkItem(29901, "https://github.com/dotnet/roslyn/issues/29901")] public void Events_03() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } } struct TS2 { event System.Action? E2; TS2(System.Action x2) { this = new TS2(); System.Action z2 = E2; System.Action y2 = E2 ?? x2; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (16,28): warning CS8600: Converting null literal or possible null value to non-nullable type. // System.Action z2 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(16, 28) ); } [Fact] public void Events_04() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL0? x1, System.Action? y1) { System.Action v1 = x1.E1 += y1; } void Test2(CL0? x2, System.Action? y2) { System.Action v2 = x2.E1 -= y2; } } class CL0 { public event System.Action? E1; void Dummy() { var x = E1; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,28): error CS0029: Cannot implicitly convert type 'void' to 'System.Action' // System.Action v1 = x1.E1 += y1; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x1.E1 += y1").WithArguments("void", "System.Action").WithLocation(10, 28), // (10,28): warning CS8602: Dereference of a possibly null reference. // System.Action v1 = x1.E1 += y1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(10, 28), // (15,28): error CS0029: Cannot implicitly convert type 'void' to 'System.Action' // System.Action v2 = x2.E1 -= y2; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x2.E1 -= y2").WithArguments("void", "System.Action").WithLocation(15, 28), // (15,28): warning CS8602: Dereference of a possibly null reference. // System.Action v2 = x2.E1 -= y2; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(15, 28) ); } [Fact] public void Events_05() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } public event System.Action E1; void Test1(Test? x1) { System.Action v1 = x1.E1; } } " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (12,28): warning CS8602: Dereference of a possibly null reference. // System.Action v1 = x1.E1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(12, 28) ); } [WorkItem(31018, "https://github.com/dotnet/roslyn/issues/31018")] [Fact] public void EventAssignment() { var source = @"#pragma warning disable 0067 using System; class A { } class B { event Action> E; static void M1() { var b1 = new B(); b1.E += F1; // 1 b1.E += F2; // 2 b1.E += F3; b1.E += F4; } static void M2(Action> f1, Action?> f2, Action> f3, Action?> f4) { var b2 = new B(); b2.E += f1; // 3 b2.E += f2; // 4 b2.E += f3; b2.E += f4; } static void M3() { var b3 = new B(); b3.E += (A a) => { }; // 5 b3.E += (A? a) => { }; // 6 b3.E += (A a) => { }; b3.E += (A? a) => { }; // 7 } static void F1(A a) { } static void F2(A? a) { } static void F3(A a) { } static void F4(A? a) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/31018: Report warnings for // 3 and // 4. comp.VerifyDiagnostics( // (10,17): warning CS8622: Nullability of reference types in type of parameter 'a' of 'void B.F1(A a)' doesn't match the target delegate 'Action>'. // b1.E += F1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F1").WithArguments("a", "void B.F1(A a)", "System.Action>").WithLocation(10, 17), // (11,17): warning CS8622: Nullability of reference types in type of parameter 'a' of 'void B.F2(A? a)' doesn't match the target delegate 'Action>'. // b1.E += F2; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F2").WithArguments("a", "void B.F2(A? a)", "System.Action>").WithLocation(11, 17), // (26,17): warning CS8622: Nullability of reference types in type of parameter 'a' of 'lambda expression' doesn't match the target delegate 'Action>'. // b3.E += (A a) => { }; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(A a) => { }").WithArguments("a", "lambda expression", "System.Action>").WithLocation(26, 17), // (27,17): warning CS8622: Nullability of reference types in type of parameter 'a' of 'lambda expression' doesn't match the target delegate 'Action>'. // b3.E += (A? a) => { }; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(A? a) => { }").WithArguments("a", "lambda expression", "System.Action>").WithLocation(27, 17), // (29,17): warning CS8622: Nullability of reference types in type of parameter 'a' of 'lambda expression' doesn't match the target delegate 'Action>'. // b3.E += (A? a) => { }; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "(A? a) => { }").WithArguments("a", "lambda expression", "System.Action>").WithLocation(29, 17)); } [Fact] public void AsOperator_01() { CSharpCompilation c = CreateCompilation(new[] { @" class Test { static void Main() { } void Test1(CL1 x1) { object y1 = x1 as object ?? new object(); } void Test2(int x2) { object y2 = x2 as object ?? new object(); } void Test3(CL1? x3) { object y3 = x3 as object; } void Test4(int? x4) { object y4 = x4 as object; } void Test5(object x5) { CL1 y5 = x5 as CL1; } void Test6() { CL1 y6 = null as CL1; } void Test7(T x7) { CL1 y7 = x7 as CL1; } } class CL1 {} " }, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (20,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y3 = x3 as object; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3 as object").WithLocation(20, 21), // (25,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y4 = x4 as object; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x4 as object").WithLocation(25, 21), // (30,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 y5 = x5 as CL1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x5 as CL1").WithLocation(30, 18), // (35,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 y6 = null as CL1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null as CL1").WithLocation(35, 18), // (40,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // CL1 y7 = x7 as CL1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x7 as CL1").WithLocation(40, 18) ); } [Fact] public void ReturningValues_IEnumerableT() { var source = @" public class C { System.Collections.Generic.IEnumerable M() { return null; // 1 } public System.Collections.Generic.IEnumerable? M2() { return null; } System.Collections.Generic.IEnumerable M3() => null; // 2 System.Collections.Generic.IEnumerable? M4() => null; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,16): warning CS8603: Possible null reference return. // return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 16), // (12,60): warning CS8603: Possible null reference return. // System.Collections.Generic.IEnumerable M3() => null; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(12, 60) ); var source2 = @" class D { void M(C c) { c.M2() /*T:System.Collections.Generic.IEnumerable?*/ ; } } "; var comp2 = CreateCompilation(source2, references: new[] { comp.EmitToImageReference() }, options: WithNonNullTypesTrue()); comp2.VerifyTypes(); } [Fact] public void Yield_IEnumerableT() { var source = @" public class C { public System.Collections.Generic.IEnumerable M() { yield return null; // 1 yield return """"; yield return null; // 2 yield break; } public System.Collections.Generic.IEnumerable M2() { yield return null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,22): warning CS8603: Possible null reference return. // yield return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 22), // (8,22): warning CS8603: Possible null reference return. // yield return null; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(8, 22) ); var source2 = @" class D { void M(C c) { c.M() /*T:System.Collections.Generic.IEnumerable!*/ ; c.M2() /*T:System.Collections.Generic.IEnumerable!*/ ; } } "; var comp2 = CreateCompilation(source2, references: new[] { comp.EmitToImageReference() }, options: WithNonNullTypesTrue()); comp2.VerifyTypes(); } [Fact] public void Yield_IEnumerableT_LocalFunction() { var source = @" class C { void Method() { _ = M(); _ = M2(); System.Collections.Generic.IEnumerable M() { yield return null; // 1 yield return """"; yield return null; // 2 yield break; } System.Collections.Generic.IEnumerable M2() { yield return null; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,26): warning CS8603: Possible null reference return. // yield return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(11, 26), // (13,26): warning CS8603: Possible null reference return. // yield return null; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(13, 26) ); } [Fact] public void Yield_IEnumerableT_GenericT() { var source = @" class C { System.Collections.Generic.IEnumerable M() { yield return default; // 1 } System.Collections.Generic.IEnumerable M1() where T : class { yield return default; // 2 } System.Collections.Generic.IEnumerable M2() where T : class? { yield return default; // 3 } System.Collections.Generic.IEnumerable M3() where T : class { yield return default; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,22): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // yield return default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 22), // (10,22): warning CS8603: Possible null reference return. // yield return default; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(10, 22), // (14,22): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // yield return default; // 3 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(14, 22) ); } [Fact] public void Yield_IEnumerableT_ErrorValue() { var source = @" class C { System.Collections.Generic.IEnumerable M() { yield return bad; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,22): error CS0103: The name 'bad' does not exist in the current context // yield return bad; Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(6, 22) ); } [Fact] public void Yield_IEnumerableT_ErrorValue2() { var source = @" static class C { static System.Collections.Generic.IEnumerable M(object? x) { yield return (C)x; } static System.Collections.Generic.IEnumerable M(object? y) { yield return (C?)y; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,22): error CS0716: Cannot convert to static type 'C' // yield return (C)x; Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C)x").WithArguments("C").WithLocation(6, 22), // (6,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // yield return (C)x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)x").WithLocation(6, 22), // (8,60): error CS0111: Type 'C' already defines a member called 'M' with the same parameter types // static System.Collections.Generic.IEnumerable M(object? y) Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M").WithArguments("M", "C").WithLocation(8, 60), // (10,22): error CS0716: Cannot convert to static type 'C' // yield return (C?)y; Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C?)y").WithArguments("C").WithLocation(10, 22) ); } [Fact] public void Yield_IEnumerableT_NoValue() { var source = @" class C { System.Collections.Generic.IEnumerable M() { yield return; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,15): error CS1627: Expression expected after yield return // yield return; Diagnostic(ErrorCode.ERR_EmptyYield, "return").WithLocation(6, 15) ); } [Fact] public void Yield_IEnumeratorT() { var source = @" class C { System.Collections.Generic.IEnumerator M() { yield return null; // 1 yield return """"; } System.Collections.Generic.IEnumerator M2() { yield return null; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,22): warning CS8603: Possible null reference return. // yield return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 22) ); } [Fact] public void Yield_IEnumeratorT_LocalFunction() { var source = @" class C { void Method() { _ = M(); _ = M2(); System.Collections.Generic.IEnumerator M() { yield return null; // 1 yield return """"; } System.Collections.Generic.IEnumerator M2() { yield return null; } } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,26): warning CS8603: Possible null reference return. // yield return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(11, 26) ); } [Fact] public void Yield_IEnumerable() { var source = @" class C { System.Collections.IEnumerable M() { yield return null; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void Yield_IEnumerator() { var source = @" class C { System.Collections.IEnumerator M() { yield return null; yield return null; } }"; CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact, CompilerTrait(CompilerFeature.AsyncStreams)] public void Yield_IAsyncEnumerable() { var source = @" using System.Collections.Generic; using System.Threading.Tasks; class C { public static async IAsyncEnumerable M() { yield return null; // 1 yield return null; // 2 await Task.Delay(1); yield break; } public static async IAsyncEnumerable M2() { yield return null; yield return null; await Task.Delay(1); } void Method() { _ = local(); _ = local2(); async IAsyncEnumerable local() { yield return null; // 3 await Task.Delay(1); yield break; } async IAsyncEnumerable local2() { yield return null; await Task.Delay(1); } } }"; CreateCompilationWithTasksExtensions(new[] { source, AsyncStreamsTypes }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,22): warning CS8603: Possible null reference return. // yield return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(8, 22), // (9,22): warning CS8603: Possible null reference return. // yield return null; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(9, 22), // (26,26): warning CS8603: Possible null reference return. // yield return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(26, 26) ); } [Fact, CompilerTrait(CompilerFeature.AsyncStreams)] public void Yield_IAsyncEnumerator() { var source = @" using System.Collections.Generic; using System.Threading.Tasks; class C { async IAsyncEnumerator M() { yield return null; // 1 yield return null; // 2 await Task.Delay(1); yield break; } async IAsyncEnumerator M2() { yield return null; yield return null; await Task.Delay(1); } void Method() { _ = local(); _ = local2(); async IAsyncEnumerator local() { yield return null; // 3 await Task.Delay(1); } async IAsyncEnumerator local2() { yield return null; await Task.Delay(1); yield break; } } }"; var comp = CreateCompilationWithTasksExtensions(new[] { source, AsyncStreamsTypes }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,22): warning CS8603: Possible null reference return. // yield return null; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(8, 22), // (9,22): warning CS8603: Possible null reference return. // yield return null; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(9, 22), // (26,26): warning CS8603: Possible null reference return. // yield return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(26, 26) ); } [Fact] public void Await_01() { var source = @" using System; static class Program { static void Main() { } static async void f() { object x = await new D() ?? new object(); } } class D { public Awaiter GetAwaiter() { return new Awaiter(); } } class Awaiter : System.Runtime.CompilerServices.INotifyCompletion { public void OnCompleted(Action x) { } public object GetResult() { throw new Exception(); } public bool IsCompleted { get { return true; } } }"; CreateCompilationWithMscorlib45(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void Await_02() { var source = @" using System; static class Program { static void Main() { } static async void f() { object x = await new D(); } } class D { public Awaiter GetAwaiter() { return new Awaiter(); } } class Awaiter : System.Runtime.CompilerServices.INotifyCompletion { public void OnCompleted(Action x) { } public object? GetResult() { throw new Exception(); } public bool IsCompleted { get { return true; } } }"; CreateCompilationWithMscorlib45(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x = await new D(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "await new D()").WithLocation(10, 20) ); } [Fact] public void Await_03() { var source = @"using System.Threading.Tasks; class Program { async void M(Task? x, Task? y) { if (y == null) return; await x; // 1 await y; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,15): warning CS8602: Dereference of a possibly null reference. // await x; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 15)); } [Fact] public void Await_ProduceResultTypeFromTask() { var source = @" class C { async void M() { var x = await Async(); x.ToString(); } System.Threading.Tasks.Task Async() => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void Await_CheckNullReceiver() { var source = @" class C { async void M() { await Async(); } System.Threading.Tasks.Task? Async() => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): warning CS8602: Dereference of a possibly null reference. // await Async(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "Async()").WithLocation(6, 15) ); } [Fact] public void Await_ExtensionGetAwaiter() { var source = @" public class Awaitable { async void M() { await Async(); } Awaitable? Async() => throw null!; } public static class Extensions { public static System.Runtime.CompilerServices.TaskAwaiter GetAwaiter(this Awaitable? x) => throw null!; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): warning CS8602: Dereference of a possibly null reference. // await Async(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "Async()").WithLocation(6, 15) ); } [Fact] public void Await_UpdateExpression() { var source = @" class C { async void M(System.Threading.Tasks.Task? task) { await task; // warn await task; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): warning CS8602: Dereference of a possibly null reference. // await task; // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "task").WithLocation(6, 15) ); } [Fact] public void Await_LearnFromNullTest() { var source = @" class C { System.Threading.Tasks.Task? M() => throw null!; async System.Threading.Tasks.Task M2(C? c) { await c?.M(); // warn c.ToString(); // no cascade } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,15): warning CS8602: Dereference of a possibly null reference. // await c?.M(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.M()").WithLocation(7, 15) ); } [Fact] public void ArrayAccess_LearnFromNullTest() { var source = @" class C { string[] field = null!; void M2(C? c) { _ = (c?.field)[0]; // warn c.ToString(); // no cascade } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,14): warning CS8602: Dereference of a possibly null reference. // _ = (c?.field)[0]; // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.field").WithLocation(7, 14) ); } [Fact] public void Call_LambdaConsidersNonFinalState() { var source = @" using System; class C { void M(string? maybeNull1, string? maybeNull2, string? maybeNull3) { M1(() => maybeNull1.Length); // 1 M2(() => maybeNull2.Length, maybeNull2 = """"); // 2 M3(maybeNull3 = """", () => maybeNull3.Length); } void M1(Func lambda) => throw null!; void M1(Func lambda) => throw null!; void M2(Func lambda, object o) => throw null!; void M3(object o, Func lambda) => throw null!; }"; var comp = CreateNullableCompilation(new[] { source }); comp.VerifyDiagnostics( // (7,18): warning CS8602: Dereference of a possibly null reference. // M1(() => maybeNull1.Length); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "maybeNull1").WithLocation(7, 18), // (8,18): warning CS8602: Dereference of a possibly null reference. // M2(() => maybeNull2.Length, maybeNull2 = ""); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "maybeNull2").WithLocation(8, 18) ); } [Fact] public void Call_LearnFromNullTest() { var source = @" class C { string M() => throw null!; C field = null!; void M2(C? c) { _ = (c?.field).M(); // warn c.ToString(); // no cascade } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8602: Dereference of a possibly null reference. // _ = (c?.field).M(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.field").WithLocation(8, 14) ); } [Fact, WorkItem(36132, "https://github.com/dotnet/roslyn/issues/36132")] public void Call_MethodTypeInferenceUsesNullabilitiesOfConvertedTypes() { var source = @" class A { } class B { public static implicit operator A(B? b) => new A(); } class C { void Test(A a, B? b) { A t1 = M(a, b); A t2 = M(a, b); // unexpected } T M(T t1, T t2) => t2; }"; var comp = CreateNullableCompilation(source); // There should be no diagnostic. See https://github.com/dotnet/roslyn/issues/36132 comp.VerifyDiagnostics( // (10,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // A t2 = M(a, b); // unexpected Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "M(a, b)").WithLocation(10, 16) ); } [Fact] public void Indexer_LearnFromNullTest() { var source = @" class C { string this[int i] => throw null!; C field = null!; void M(C? c) { _ = (c?.field)[0]; // warn c.ToString(); // no cascade } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8602: Dereference of a possibly null reference. // _ = (c?.field)[0]; // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.field").WithLocation(8, 14) ); } [Fact] public void MemberAccess_LearnFromNullTest() { var source = @" class C { string this[int i] => throw null!; C field = null!; void M(C? c) { _ = (c?.field).field; // warn c.ToString(); // no cascade } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8602: Dereference of a possibly null reference. // _ = (c?.field).field; // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.field").WithLocation(8, 14) ); } [Theory, WorkItem(31906, "https://github.com/dotnet/roslyn/issues/31906")] [InlineData("==")] [InlineData(">")] [InlineData("<")] [InlineData(">=")] [InlineData("<=")] public void LearnFromNullTest_FromOperatorOnConstant(string op) { var source = @" class C { static void F(string? s, string? s2) { if (s?.Length OPERATOR 1) s.ToString(); else s.ToString(); // 1 if (1 OPERATOR s2?.Length) s2.ToString(); else s2.ToString(); // 2 } }"; var comp = CreateCompilation(source.Replace("OPERATOR", op), options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(14, 13) ); } [Fact] public void LearnFromNullTest_IncludingConstants() { var source = @" class C { void F() { const string s1 = """"; if (s1 == null) s1.ToString(); // 1 if (null == s1) s1.ToString(); // 2 if (s1 != null) s1.ToString(); else s1.ToString(); // 3 if (null != s1) s1.ToString(); else s1.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS0162: Unreachable code detected // s1.ToString(); // 1 Diagnostic(ErrorCode.WRN_UnreachableCode, "s1").WithLocation(8, 13), // (11,13): warning CS0162: Unreachable code detected // s1.ToString(); // 2 Diagnostic(ErrorCode.WRN_UnreachableCode, "s1").WithLocation(11, 13), // (16,13): warning CS0162: Unreachable code detected // s1.ToString(); // 3 Diagnostic(ErrorCode.WRN_UnreachableCode, "s1").WithLocation(16, 13), // (21,13): warning CS0162: Unreachable code detected // s1.ToString(); // 4 Diagnostic(ErrorCode.WRN_UnreachableCode, "s1").WithLocation(21, 13) ); } [Fact, WorkItem(31906, "https://github.com/dotnet/roslyn/issues/31906")] public void LearnFromNullTest_NotEqualsConstant() { var source = @" class C { static void F(string? s, string? s2) { if (s?.Length != 1) s.ToString(); // 1 else s.ToString(); if (1 != s2?.Length) s2.ToString(); // 2 else s2.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(12, 13) ); } [Fact, WorkItem(31906, "https://github.com/dotnet/roslyn/issues/31906")] public void LearnFromNullTest_FromIsConstant() { var source = @" class C { static void F(string? s) { if (s?.Length is 1) s.ToString(); else s.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13) ); } [Fact] public void NoPiaObjectCreation_01() { string pia = @" using System; using System.Runtime.InteropServices; [assembly: ImportedFromTypeLib(""GeneralPIA.dll"")] [assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] [ComImport()] [Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58277"")] [CoClass(typeof(ClassITest28))] public interface ITest28 { } [Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58278"")] public abstract class ClassITest28 //: ITest28 { public ClassITest28(int x){} } "; var piaCompilation = CreateCompilationWithMscorlib45(pia, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7); CompileAndVerify(piaCompilation); string source = @" class UsePia { public static void Main() { } void Test1(ITest28 x1) { x1 = new ITest28(); } void Test2(ITest28 x2) { x2 = new ITest28() ?? x2; } }"; var compilation = CreateCompilationWithMscorlib45(new[] { source }, new MetadataReference[] { new CSharpCompilationReference(piaCompilation, embedInteropTypes: true) }, options: WithNonNullTypesTrue(TestOptions.DebugExe)); compilation.VerifyDiagnostics( ); } [Fact] public void SymbolDisplay_01() { var source = @" abstract class B { string? F1; event System.Action? E1; string? P1 {get; set;} string?[][,] P2 {get; set;} System.Action M1(string? x) {return null;} string[]?[,] M2(string[][,]? x) {return null;} void M3(string?* x) {} public abstract string? this[System.Action? x] {get; set;} public static implicit operator B?(int x) { return null; } } delegate string? D1(); interface I1{} interface I2{} class C {} class F : C, I1>, I2?> {} "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var b = compilation.GetTypeByMetadataName("B"); Assert.Equal("System.String? B.F1", b.GetMember("F1").ToTestDisplayString()); Assert.Equal("event System.Action? B.E1", b.GetMember("E1").ToTestDisplayString()); Assert.Equal("System.String? B.P1 { get; set; }", b.GetMember("P1").ToTestDisplayString()); Assert.Equal("System.String?[][,] B.P2 { get; set; }", b.GetMember("P2").ToTestDisplayString()); Assert.Equal("System.Action B.M1(System.String? x)", b.GetMember("M1").ToTestDisplayString()); Assert.Equal("System.String[]?[,] B.M2(System.String[][,]? x)", b.GetMember("M2").ToTestDisplayString()); Assert.Equal("void B.M3(System.String?* x)", b.GetMember("M3").ToTestDisplayString()); Assert.Equal("System.String? B.this[System.Action? x] { get; set; }", b.GetMember("this[]").ToTestDisplayString()); Assert.Equal("B.implicit operator B?(int)", b.GetMember("op_Implicit").ToDisplayString()); Assert.Equal("String? D1()", compilation.GetTypeByMetadataName("D1") .ToDisplayString(new SymbolDisplayFormat(delegateStyle: SymbolDisplayDelegateStyle.NameAndSignature, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier))); var f = compilation.GetTypeByMetadataName("F"); Assert.Equal("C", f.BaseType().ToTestDisplayString()); Assert.Equal("I1>", f.Interfaces()[0].ToTestDisplayString()); Assert.Equal("I2?>", f.Interfaces()[1].ToTestDisplayString()); } [Fact] public void NullableAttribute_01() { var source = @"#pragma warning disable 8618 public abstract class B { public string? F1; public event System.Action? E1; public string? P1 {get; set;} public string?[][,] P2 {get; set;} public System.Action M1(string? x) {throw new System.NotImplementedException();} public string[]?[,] M2(string[][,]? x) {throw new System.NotImplementedException();} public abstract string? this[System.Action? x] {get; set;} public static implicit operator B?(int x) {throw new System.NotImplementedException();} public event System.Action? E2 { add { } remove { } } } public delegate string? D1(); public interface I1{} public interface I2{} public class C {} public class F : C, I1>, I2?> {} "; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (5,33): warning CS0067: The event 'B.E1' is never used // public event System.Action? E1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E1").WithArguments("B.E1").WithLocation(5, 33) ); CompileAndVerify(compilation, symbolValidator: m => { var b = ((PEModuleSymbol)m).GlobalNamespace.GetTypeMember("B"); Assert.Equal("System.String? B.F1", b.GetMember("F1").ToTestDisplayString()); Assert.Equal("event System.Action? B.E1", b.GetMember("E1").ToTestDisplayString()); Assert.Equal("System.String? B.P1 { get; set; }", b.GetMember("P1").ToTestDisplayString()); Assert.Equal("System.String?[][,] B.P2 { get; set; }", b.GetMember("P2").ToTestDisplayString()); Assert.Equal("System.Action B.M1(System.String? x)", b.GetMember("M1").ToTestDisplayString()); Assert.Equal("System.String[]?[,] B.M2(System.String[][,]? x)", b.GetMember("M2").ToTestDisplayString()); Assert.Equal("System.String? B.this[System.Action? x] { get; set; }", b.GetMember("this[]").ToTestDisplayString()); Assert.Equal("B.implicit operator B?(int)", b.GetMember("op_Implicit").ToDisplayString()); Assert.Equal("event System.Action? B.E2", b.GetMember("E2").ToTestDisplayString()); Assert.Equal("String? D1()", compilation.GetTypeByMetadataName("D1") .ToDisplayString(new SymbolDisplayFormat(delegateStyle: SymbolDisplayDelegateStyle.NameAndSignature, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier))); var f = ((PEModuleSymbol)m).GlobalNamespace.GetTypeMember("F"); Assert.Equal("C", f.BaseType().ToTestDisplayString()); Assert.Equal("I1>", f.Interfaces()[0].ToTestDisplayString()); Assert.Equal("I2?>", f.Interfaces()[1].ToTestDisplayString()); }); } [Fact] public void NullableAttribute_02() { CSharpCompilation c0 = CreateCompilation(new[] { @" public class CL0 { public object F1; public object? P1 { get; set;} } " }, options: WithNonNullTypesTrue(TestOptions.DebugDll)); string source = @" class C { static void Main() { } void Test1(CL0 x1, object? y1) { x1.F1 = y1; } void Test2(CL0 x2, object y2) { y2 = x2.P1; } } "; var expected = new[] { // (10,17): warning CS8601: Possible null reference assignment. // x1.F1 = y1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y1").WithLocation(10, 17), // (15,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = x2.P1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2.P1").WithLocation(15, 14) }; CSharpCompilation c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { c0.ToMetadataReference() }); c.VerifyDiagnostics(expected); } [Fact] public void NullableAttribute_03() { CSharpCompilation c0 = CreateCompilation(new[] { @" public class CL0 { public object F1; } " }, options: WithNonNullTypesTrue(TestOptions.DebugDll)); string source = @" class C { static void Main() { } void Test1(CL0 x1, object? y1) { x1.F1 = y1; } } "; var expected = new[] { // (10,17): warning CS8601: Possible null reference assignment. // x1.F1 = y1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y1").WithLocation(10, 17) }; CSharpCompilation c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { c0.EmitToImageReference() }); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { c0.ToMetadataReference() }); c.VerifyDiagnostics(expected); } [Fact] public void NullableAttribute_04() { var source = @"#pragma warning disable 8618 using System.Runtime.CompilerServices; public abstract class B { [Nullable(0)] public string F1; [Nullable(1)] public event System.Action E1; [Nullable(2)] public string[][,] P2 {get; set;} [return:Nullable(0)] public System.Action M1(string? x) {throw new System.NotImplementedException();} public string[][,] M2([Nullable(new byte[] {0})] string[][,] x) {throw new System.NotImplementedException();} } public class C {} [Nullable(2)] public class F : C {} "; var compilation = CreateCompilation(new[] { source, NullableAttributeDefinition }, options: WithNonNullTypesTrue()); compilation.VerifyDiagnostics( // (7,6): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [Nullable(1)] public event System.Action E1; Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(1)").WithLocation(7, 6), // (8,6): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [Nullable(2)] public string[][,] P2 {get; set;} Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(2)").WithLocation(8, 6), // (9,13): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [return:Nullable(0)] public System.Action M1(string? x) Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(9, 13), // (11,28): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // public string[][,] M2([Nullable(new byte[] {0})] string[][,] x) Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(new byte[] {0})").WithLocation(11, 28), // (6,6): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [Nullable(0)] public string F1; Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(6, 6), // (17,2): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [Nullable(2)] public class F : C Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(2)").WithLocation(17, 2), // (7,46): warning CS0067: The event 'B.E1' is never used // [Nullable(1)] public event System.Action E1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E1").WithArguments("B.E1").WithLocation(7, 46) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_01() { string lib = @" using System; public class CL0 { public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { public event Action E1; public event Action? E2; #nullable disable void Test11(Action? x11) { E1 = x11; } #nullable disable void Test12(Action x12) { x12 = E1 ?? x12; } #nullable disable void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; partial class C { partial class B { #nullable disable void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } #nullable disable void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } #nullable disable void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); CSharpCompilation c1 = CreateCompilation(new[] { lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); } [Fact] public void NonNullTypes_02() { string lib = @" using System; #nullable disable public class CL0 { #nullable disable public class CL1 { #nullable enable #pragma warning disable 8618 public Action F1; #nullable enable #pragma warning disable 8618 public Action? F2; #nullable enable #pragma warning disable 8618 public Action P1 { get; set; } #nullable enable public Action? P2 { get; set; } #nullable enable public Action M1() { throw new System.NotImplementedException(); } #nullable enable public Action? M2() { return null; } #nullable enable public void M3(Action x3) {} } } "; string source1 = @"#pragma warning disable 8618 using System; partial class C { partial class B { #nullable enable public event Action E1; #nullable enable public event Action? E2; #nullable enable void Test11(Action? x11) { E1 = x11; } #nullable enable void Test12(Action x12) { x12 = E1 ?? x12; } #nullable enable void Test13(Action x13) { x13 = E2; } } } "; string source2 = @"#pragma warning disable 8618 using System; #nullable disable partial class C { #nullable disable partial class B { #nullable enable void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } #nullable enable void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } #nullable enable void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c.VerifyDiagnostics( // (18,18): warning CS8601: Possible null reference assignment. // E1 = x11; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x11").WithLocation(18, 18), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), // (13,20): warning CS8601: Possible null reference assignment. // c.F1 = x21; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x21").WithLocation(13, 20), // (14,20): warning CS8601: Possible null reference assignment. // c.P1 = x21; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { lib }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c1.VerifyDiagnostics(); var expected = new[] { // (13,20): warning CS8601: Possible null reference assignment. // c.F1 = x21; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x21").WithLocation(13, 20), // (14,20): warning CS8601: Possible null reference assignment. // c.P1 = x21; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) }; c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c.VerifyDiagnostics(expected); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void NonNullTypes_03() { string lib = @" using System; public class CL0 { public class CL1 { #nullable enable public Action F1 = null!; #nullable enable public Action? F2; #nullable enable public Action P1 { get; set; } = null!; #nullable enable public Action? P2 { get; set; } #nullable enable public Action M1() { throw new System.NotImplementedException(); } #nullable enable public Action? M2() { return null; } #nullable enable public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { #nullable enable public event Action E1; #nullable enable public event Action? E2; #nullable disable void Test11(Action? x11) // 1 { E1 = x11; // 2 } void Test12(Action x12) { x12 = E1 ?? x12; // 3 } void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; partial class C { partial class B { void Test21(CL0.CL1 c, Action? x21) // 4 { c.F1 = x21; // 5 c.P1 = x21; // 6 c.M3(x21); // 7 } void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; // 8 x22 = c.P1 ?? x22; // 9 x22 = c.M1() ?? x22; // 10 } void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c.VerifyDiagnostics( // (15,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test11(Action? x11) // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 27), // (8,38): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test21(CL0.CL1 c, Action? x21) // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 38) ); CSharpCompilation c1 = CreateCompilation(new[] { lib }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c1.VerifyDiagnostics(); var expectedDiagnostics = new[] { // (8,38): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test21(CL0.CL1 c, Action? x21) // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 38) }; c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c.VerifyDiagnostics(expectedDiagnostics); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesFalse()); c.VerifyDiagnostics(expectedDiagnostics); expectedDiagnostics = new[] { // (10,20): warning CS8601: Possible null reference assignment. // c.F1 = x21; // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x21").WithLocation(10, 20), // (11,20): warning CS8601: Possible null reference assignment. // c.P1 = x21; // 6 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x21").WithLocation(11, 20), // (12,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(12, 18), // (24,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(24, 19), // (25,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(25, 19), // (26,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(26, 19) }; c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(expectedDiagnostics); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(expectedDiagnostics); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void NonNullTypes_04() { string lib = @" using System; #nullable disable public class CL0 { public class CL1 { #nullable enable public Action F1 = null!; #nullable enable public Action? F2; #nullable enable public Action P1 { get; set; } = null!; #nullable enable public Action? P2 { get; set; } #nullable enable public Action M1() { throw new System.NotImplementedException(); } #nullable enable public Action? M2() { return null; } #nullable enable public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { #nullable enable public event Action E1; #nullable enable public event Action? E2; void Test11(Action? x11) // 1 { E1 = x11; // 2 } void Test12(Action x12) { x12 = E1 ?? x12; // 3 } void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; #nullable disable partial class C { partial class B { void Test21(CL0.CL1 c, Action? x21) // 4 { c.F1 = x21; // 5 c.P1 = x21; // 6 c.M3(x21); // 7 } void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; // 8 x22 = c.P1 ?? x22; // 9 x22 = c.M1() ?? x22; // 10 } void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (9,38): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test21(CL0.CL1 c, Action? x21) // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 38), // (15,18): warning CS8601: Possible null reference assignment. // E1 = x11; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x11").WithLocation(15, 18), // (25,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(25, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { lib }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c1.VerifyDiagnostics(); var expected = new[] { // (9,38): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test21(CL0.CL1 c, Action? x21) // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 38) }; c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(expected); } [WorkItem(30840, "https://github.com/dotnet/roslyn/issues/30840")] [Fact] public void NonNullTypes_05() { string lib = @" using System; #nullable enable public class CL0 { #nullable disable public class CL1 { #nullable enable public Action F1 = null!; #nullable enable public Action? F2; #nullable enable public Action P1 { get; set; } = null!; #nullable enable public Action? P2 { get; set; } #nullable enable public Action M1() { throw new System.NotImplementedException(); } #nullable enable public Action? M2() { return null; } #nullable enable public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { #nullable enable public event Action E1; #nullable enable public event Action? E2; void Test11(Action? x11) // 1 { E1 = x11; // 2 } void Test12(Action x12) { x12 = E1 ?? x12; // 3 } void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; #nullable enable partial class C { #nullable disable partial class B { void Test21(CL0.CL1 c, Action? x21) // 4 { c.F1 = x21; // 5 c.P1 = x21; // 6 c.M3(x21); // 7 } void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; // 8 x22 = c.P1 ?? x22; // 9 x22 = c.M1() ?? x22; // 10 } void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (10,38): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test21(CL0.CL1 c, Action? x21) // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 38), // (15,18): warning CS8601: Possible null reference assignment. // E1 = x11; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x11").WithLocation(15, 18), // (25,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(25, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { lib }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c1.VerifyDiagnostics(); var expected = new[] { // (10,38): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void Test21(CL0.CL1 c, Action? x21) // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 38) }; c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics(expected); } [Fact] public void NonNullTypes_06() { string lib = @" using System; #nullable enable public class CL0 { #nullable enable public class CL1 { #nullable disable public Action F1 = null!; #nullable disable public Action? F2; #nullable disable public Action P1 { get; set; } = null!; #nullable disable public Action? P2 { get; set; } #nullable disable public Action M1() { throw new System.NotImplementedException(); } #nullable disable public Action? M2() { return null; } #nullable disable public void M3(Action x3) {} } } "; string source1 = @" using System; #nullable enable partial class C { #nullable enable partial class B { #nullable disable public event Action E1; #nullable disable public event Action? E2; #nullable enable void Test11(Action? x11) { E1 = x11; } #nullable enable void Test12(Action x12) { x12 = E1 ?? x12; } #nullable enable void Test13(Action x13) { x13 = E2; // warn 1 } } } "; string source2 = @" using System; partial class C { partial class B { #nullable enable void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } #nullable enable void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } #nullable enable void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; // warn 2 x23 = c.P2; // warn 3 x23 = c.M2(); // warn 4 } } } "; CSharpCompilation c = CreateCompilation(new[] { lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (13,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public Action? F2; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 22), // (18,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public Action? P2 { get; set; } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 22), // (23,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public Action? M2() { return null; } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 22), // (13,28): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public event Action? E2; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 28), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; // warn 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), // (27,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; // warn 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(27, 19), // (28,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; // warn 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(28, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); // warn 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(29, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { lib }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c1.VerifyDiagnostics( // (13,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public Action? F2; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 22), // (18,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public Action? P2 { get; set; } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 22), // (23,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public Action? M2() { return null; } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 22) ); c = CreateCompilation(new[] { source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (27,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; // warn 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(27, 19), // (28,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; // warn 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(28, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); // warn 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(29, 19) ); c = CreateCompilation(new[] { source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (27,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; // warn 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(27, 19), // (28,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; // warn 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(28, 19), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); // warn 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(29, 19) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_07() { string moduleAttributes = @" [module:System.Runtime.CompilerServices.NonNullTypes(true)] "; string lib = @" using System; [System.Runtime.CompilerServices.NonNullTypes(true)] public class CL0 { [System.Runtime.CompilerServices.NonNullTypes(false)] public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; [System.Runtime.CompilerServices.NonNullTypes(true)] partial class C { [System.Runtime.CompilerServices.NonNullTypes(false)] partial class B { public event Action E1; public event Action? E2; [System.Runtime.CompilerServices.NonNullTypes(true)] void Test11(Action? x11) { E1 = x11; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test12(Action x12) { x12 = E1 ?? x12; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; partial class C { partial class B { [System.Runtime.CompilerServices.NonNullTypes(true)] void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { moduleAttributes, lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); CSharpCompilation c1 = CreateCompilation(new[] { moduleAttributes, lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_08() { string moduleAttributes = @" [module:System.Runtime.CompilerServices.NonNullTypes(true)] "; string lib = @" using System; [System.Runtime.CompilerServices.NonNullTypes(false)] public class CL0 { public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; [System.Runtime.CompilerServices.NonNullTypes(false)] partial class C { partial class B { public event Action E1; public event Action? E2; [System.Runtime.CompilerServices.NonNullTypes(true)] void Test11(Action? x11) { E1 = x11; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test12(Action x12) { x12 = E1 ?? x12; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; partial class C { partial class B { [System.Runtime.CompilerServices.NonNullTypes(true)] void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { moduleAttributes, lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); CSharpCompilation c1 = CreateCompilation(new[] { moduleAttributes, lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_09() { string moduleAttributes = @" [module:System.Runtime.CompilerServices.NonNullTypes(false)] "; string lib = @" using System; public class CL0 { public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { public event Action E1; public event Action? E2; [System.Runtime.CompilerServices.NonNullTypes(true)] void Test11(Action? x11) { E1 = x11; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test12(Action x12) { x12 = E1 ?? x12; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; partial class C { partial class B { [System.Runtime.CompilerServices.NonNullTypes(true)] void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } [System.Runtime.CompilerServices.NonNullTypes(true)] void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { moduleAttributes, lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); CSharpCompilation c1 = CreateCompilation(new[] { moduleAttributes, lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_10() { string moduleAttributes = @" [module:System.Runtime.CompilerServices.NonNullTypes(false)] "; string lib = @" using System; [System.Runtime.CompilerServices.NonNullTypes(false)] public class CL0 { [System.Runtime.CompilerServices.NonNullTypes(true)] public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { public event Action E1; public event Action? E2; void Test11(Action? x11) { E1 = x11; } void Test12(Action x12) { x12 = E1 ?? x12; } void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; [System.Runtime.CompilerServices.NonNullTypes(false)] partial class C { [System.Runtime.CompilerServices.NonNullTypes(true)] partial class B { void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { moduleAttributes, lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // E1 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(18, 18), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { moduleAttributes, lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); var expected = new[] { // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) }; c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(expected); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_11() { string moduleAttributes = @" [module:System.Runtime.CompilerServices.NonNullTypes(false)] "; string lib = @" using System; [System.Runtime.CompilerServices.NonNullTypes(true)] public class CL0 { public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { public event Action E1; public event Action? E2; void Test11(Action? x11) { E1 = x11; } void Test12(Action x12) { x12 = E1 ?? x12; } void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; [System.Runtime.CompilerServices.NonNullTypes(true)] partial class C { partial class B { void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { moduleAttributes, lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // E1 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(18, 18), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { moduleAttributes, lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); var expected = new[] { // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) }; c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(expected); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_12() { string moduleAttributes = @" [module:System.Runtime.CompilerServices.NonNullTypes(true)] "; string lib = @" using System; public class CL0 { public class CL1 { public Action F1; public Action? F2; public Action P1 { get; set; } public Action? P2 { get; set; } public Action M1() { throw new System.NotImplementedException(); } public Action? M2() { return null; } public void M3(Action x3) {} } } "; string source1 = @" using System; partial class C { partial class B { public event Action E1; public event Action? E2; void Test11(Action? x11) { E1 = x11; } void Test12(Action x12) { x12 = E1 ?? x12; } void Test13(Action x13) { x13 = E2; } } } "; string source2 = @" using System; partial class C { partial class B { void Test21(CL0.CL1 c, Action? x21) { c.F1 = x21; c.P1 = x21; c.M3(x21); } void Test22(CL0.CL1 c, Action x22) { x22 = c.F1 ?? x22; x22 = c.P1 ?? x22; x22 = c.M1() ?? x22; } void Test23(CL0.CL1 c, Action x23) { x23 = c.F2; x23 = c.P2; x23 = c.M2(); } } } "; CSharpCompilation c = CreateCompilation(new[] { moduleAttributes, lib, source1, source2 }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (18,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // E1 = x11; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x11").WithLocation(18, 18), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x13 = E2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "E2").WithLocation(30, 19), // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) ); CSharpCompilation c1 = CreateCompilation(new[] { moduleAttributes, lib }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c1.VerifyDiagnostics(); var expected = new[] { // (13,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.F1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(13, 20), // (14,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // c.P1 = x21; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x21").WithLocation(14, 20), // (15,18): warning CS8604: Possible null reference argument for parameter 'x3' in 'void CL1.M3(Action x3)'. // c.M3(x21); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x21").WithArguments("x3", "void CL1.M3(Action x3)").WithLocation(15, 18), // (29,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.F2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F2").WithLocation(29, 19), // (30,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.P2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.P2").WithLocation(30, 19), // (31,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // x23 = c.M2(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.M2()").WithLocation(31, 19) }; c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.ToMetadataReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(expected); c = CreateCompilation(new[] { moduleAttributes, source2 }, new[] { c1.EmitToImageReference() }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics(expected); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_13() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] string?[]? M1() { return null; } void Test1() { M1().ToString(); M1()[0].ToString(); var x1 = M1()[0] ?? """"; } [System.Runtime.CompilerServices.NonNullTypes(false)] string[] M2() { return null; } void Test2() { M2()[0] = null; var x2 = M2()[0] ?? """"; } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_14() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] CL1? M1() { return null; } void Test1() { M1().ToString(); M1().P1.ToString(); var x1 = M1().P1 ?? """"; } [System.Runtime.CompilerServices.NonNullTypes(false)] CL1 M2() { return null; } void Test2() { M2().P1 = null; var x2 = M2().P1 ?? """"; } CL1 M3() { return new CL1(); } void Test3() { M3().ToString(); M3().P1.ToString(); var x3 = M3().P1 ?? """"; } CL1 M4() { return new CL1(); } void Test4() { M4().P1 = null; var x4 = M4().P1 ?? """"; M4().P1.ToString(); } } class CL1 { public T P1; } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (39,9): warning CS8602: Dereference of a possibly null reference. // M3().P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3().P1").WithLocation(39, 9), // (50,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // M4().P1 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(50, 19) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_15() { string source = @" class C { void Main() {} } class CL1 { public virtual CL1 M1() { return new CL1(); } } class CL2 : CL1 { public override CL1 M1() // 2 { return base.M1(); } } class CL3 : CL1 { public override CL1 M1() { return base.M1(); } } class CL4 where T : class { [System.Runtime.CompilerServices.NonNullTypes(false)] public virtual CL4 M4() { return new CL4(); } } class CL5 : CL4 { public override CL4 M4() { return base.M4(); } } class CL6 : CL4 { public override CL4 M4() // 6 { return base.M4(); } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (17,34): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override CL1 M1() // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M1").WithLocation(17, 34), // (19,16): warning CS8619: Nullability of reference types in value of type 'CL1' doesn't match target type 'CL1'. // return base.M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "base.M1()").WithArguments("CL1", "CL1").WithLocation(19, 16), // (50,33): warning CS8609: Nullability of reference types in return type doesn't match overridden member. // public override CL4 M4() // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride, "M4").WithLocation(50, 33), // (52,16): warning CS8619: Nullability of reference types in value of type 'CL4' doesn't match target type 'CL4'. // return base.M4(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "base.M4()").WithArguments("CL4", "CL4").WithLocation(52, 16) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_16() { string source = @" class C { void Main() {} } class CL1 { public virtual void M1(CL1 x1) { } } class CL2 : CL1 { public override void M1(CL1 x2) // 2 { } } class CL3 : CL1 { public override void M1(CL1 x3) { } } class CL4 where T : class { [System.Runtime.CompilerServices.NonNullTypes(false)] public virtual void M4(CL4 x4) { } } class CL5 : CL4 { public override void M4(CL4 x5) { } } class CL6 : CL4 { public override void M4(CL4 x6) // 6 { } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (16,26): warning CS8610: Nullability of reference types in type of parameter 'x2' doesn't match overridden member. // public override void M1(CL1 x2) // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M1").WithArguments("x2").WithLocation(16, 26), // (45,26): warning CS8610: Nullability of reference types in type of parameter 'x6' doesn't match overridden member. // public override void M4(CL4 x6) // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride, "M4").WithArguments("x6").WithLocation(45, 26) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_17() { string source = @" class C { void Main() {} void Test1() { CL0.M1().ToString(); var x1 = CL0.M1() ?? """"; } } [System.Runtime.CompilerServices.NonNullTypes(false)] class CL0 { public static T M1() { return default(T); } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // CL0.M1().ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "CL0.M1()").WithLocation(8, 9) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_18() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] CL1? M1 { get; set; } void Test1() { M1.ToString(); M1.P1.ToString(); var x1 = M1.P1 ?? """"; } [System.Runtime.CompilerServices.NonNullTypes(false)] CL1 M2 { get; set; } void Test2() { M2.P1 = null; var x2 = M2.P1 ?? """"; } CL1 M3 { get; set; } void Test3() { M3.ToString(); M3.P1.ToString(); var x3 = M3.P1 ?? """"; } CL1 M4 { get; set; } void Test4() { M4.P1 = null; var x4 = M4.P1 ?? """"; } } class CL1 { public T P1; } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (30,9): warning CS8602: Dereference of a possibly null reference. // M3.P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3.P1").WithLocation(30, 9), // (38,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // M4.P1 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 17) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_19() { string source = @" class C { void Main() {} void Test1() { CL0.M1.ToString(); var x1 = CL0.M1 ?? """"; } } [System.Runtime.CompilerServices.NonNullTypes(false)] class CL0 { public static T M1 { get; set; } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // CL0.M1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "CL0.M1").WithLocation(8, 9) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_20() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] CL1? M1; void Test1() { M1.ToString(); M1.P1.ToString(); var x1 = M1.P1 ?? """"; } [System.Runtime.CompilerServices.NonNullTypes(false)] CL1 M2; void Test2() { M2.P1 = null; var x2 = M2.P1 ?? """"; } CL1 M3; void Test3() { M3.ToString(); M3.P1.ToString(); var x3 = M3.P1 ?? """"; } CL1 M4; void Test4() { M4.P1 = null; var x4 = M4.P1 ?? """"; } [System.Runtime.CompilerServices.NonNullTypes(false)] void Assign() { M1 = null; M2 = null; M3 = null; M4 = null; } } class CL1 { public T P1; } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (30,9): warning CS8602: Dereference of a possibly null reference. // M3.P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3.P1").WithLocation(30, 9), // (38,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // M4.P1 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(38, 17) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_21() { string source = @" class C { void Main() {} void Test1() { CL0.M1.ToString(); var x1 = CL0.M1 ?? """"; } } [System.Runtime.CompilerServices.NonNullTypes(false)] class CL0 { public static T M1 = default(T); } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // CL0.M1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "CL0.M1").WithLocation(8, 9) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_22() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] event System.Func? M1; void Test1() { M1.ToString(); M1().ToString(); var x1 = M1() ?? """"; } [System.Runtime.CompilerServices.NonNullTypes(false)] event System.Func M2; void Test2() { var x2 = M2() ?? """"; } event System.Func M3; void Test3() { M3.ToString(); M3().ToString(); var x3 = M3() ?? """"; } event System.Func M4; void Test4() { var x4 = M4() ?? """"; M4().ToString(); } [System.Runtime.CompilerServices.NonNullTypes(false)] void Assign() { M1 = null; M2 = null; M3 = null; M4 = null; } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (29,9): warning CS8602: Dereference of a possibly null reference. // M3().ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M3()").WithLocation(29, 9) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_23() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] delegate void D1 (CL1? x1); void M1(D1 x1) {} void Test1() { M1(a1 => a1.ToString()); M1(b1 => b1.P1.ToString()); M1(c1 => {var x1 = c1.P1 ?? """";}); } [System.Runtime.CompilerServices.NonNullTypes(false)] delegate void D2(CL1 x2); void M2(D2 x2) {} void Test2() { M2(a2 => {a2.P1 = null;}); M2(b2 => {var x2 = b2.P1 ?? """";}); } delegate void D3 (CL1 x3); void M3(D3 x3) {} void Test3() { M3(a3 => a3.ToString()); M3(b3 => b3.P1.ToString()); M3(c3 => {var x3 = c3.P1 ?? """";}); } delegate void D4(CL1 x4); void M4(D4 x4) {} void Test4() { M4(a4 => {a4.P1 = null;}); M4(b4 => {var x4 = b4.P1 ?? """";}); } void Test11() { D1 u11 = a11 => a11.ToString(); D1 v11 = b11 => b11.P1.ToString(); D1 w11 = c11 => {var x11 = c11.P1 ?? """";}; } void Test21() { D2 u21 = a21 => {a21.P1 = null;}; D2 v21 = b21 => {var x21 = b21.P1 ?? """";}; } void Test31() { D3 u31 = a31 => a31.ToString(); D3 v31 = b31 => b31.P1.ToString(); D3 w31 = c31 => {var x31 = c31.P1 ?? """";}; } void Test41() { D4 u41 = a41 => {a41.P1 = null;}; D4 v41 = b41 => {var x41 = b41.P1 ?? """";}; } } class CL1 { public T P1; } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (35,18): warning CS8602: Dereference of a possibly null reference. // M3(b3 => b3.P1.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b3.P1").WithLocation(35, 18), // (44,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // M4(a4 => {a4.P1 = null;}); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(44, 27), // (64,25): warning CS8602: Dereference of a possibly null reference. // D3 v31 = b31 => b31.P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b31.P1").WithLocation(64, 25), // (70,35): warning CS8600: Converting null literal or possible null value to non-nullable type. // D4 u41 = a41 => {a41.P1 = null;}; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(70, 35) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_24() { string source = @" class C { void Main() {} void M1(CL0 x1) {} void Test1() { M1(a1 => a1.ToString()); M1(b1 => {var x1 = b1 ?? """";}); } void Test2() { CL0 u2 = a2 => a2.ToString(); CL0 v2 = b2 => {var x2 = b2 ?? """";}; } [System.Runtime.CompilerServices.NonNullTypes(false)] void M2(CL0 x1) {} void Test3() { M2(a3 => a3.ToString()); M2(b3 => {var x3 = b3 ?? """";}); } [System.Runtime.CompilerServices.NonNullTypes(false)] void M3(CL1 x1) {} void Test4() { M3(a4 => a4.ToString()); M3(b4 => {var x4 = b4 ?? """";}); } void M4(CL1 x1) {} void Test5() { M4(a5 => a5.ToString()); M4(b5 => {var x5 = b5 ?? """";}); } [System.Runtime.CompilerServices.NonNullTypes(false)] void M5(CL2 x1) {} void Test6() { M5(a6 => a6.ToString()); M5(b6 => {var x6 = b6 ?? """";}); } } [System.Runtime.CompilerServices.NonNullTypes(false)] delegate void CL0(T x); [System.Runtime.CompilerServices.NonNullTypes(false)] delegate void CL1(T? x) where T : class; delegate void CL2(T? x) where T : class; "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (10,18): warning CS8602: Dereference of a possibly null reference. // M1(a1 => a1.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a1").WithLocation(10, 18), // (16,33): warning CS8602: Dereference of a possibly null reference. // CL0 u2 = a2 => a2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2").WithLocation(16, 33), // (42,18): warning CS8602: Dereference of a possibly null reference. // M4(a5 => a5.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a5").WithLocation(42, 18), // (51,18): warning CS8602: Dereference of a possibly null reference. // M5(a6 => a6.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a6").WithLocation(51, 18) ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_25() { string source = @" class C { void Main() {} [System.Runtime.CompilerServices.NonNullTypes(false)] delegate string D1 (); void M1(D1 x1) {} void Test1() { M1(() => null); } void Test2() { D1 x2 = () => null; } delegate T D3 (); [System.Runtime.CompilerServices.NonNullTypes(false)] void M3(D3 x3) {} void Test3() { M3(() => null); } } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( ); } [WorkItem(29616, "https://github.com/dotnet/roslyn/issues/29616")] [Fact(Skip = "NonNullTypes does not control warnings")] public void NonNullTypes_26() { string source = @" class C { void Main() {} void M1(CL0 x1) {} void Test1() { M1(() => null); } void Test2() { CL0 x2 =() => null; } [System.Runtime.CompilerServices.NonNullTypes(false)] void M2(D2 x2) {} void Test3() { M2(() => null); } } [System.Runtime.CompilerServices.NonNullTypes(false)] delegate T CL0(); delegate string D2(); "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // (10,18): warning CS8603: Possible null reference return. // M1(() => null); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(10, 18), // (15,31): warning CS8603: Possible null reference return. // CL0 x2 =() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(15, 31), // (23,18): warning CS8603: Possible null reference return. // M2(() => null); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(23, 18) ); } [Fact] public void Covariance_Interface() { var source = @"interface I { } class C { static I F1(I i) => i; static I F2(I i) => i; static I F3(I i) => i; static I F4(I i) => i; }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,42): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static I F3(I i) => i; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "i").WithArguments("I", "I").WithLocation(6, 42), // (7,42): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static I F4(I i) => i; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "i").WithArguments("I", "I").WithLocation(7, 42)); } [Fact] public void Contravariance_Interface() { var source = @"interface I { } class C { static I F1(I i) => i; static I F2(I i) => i; static I F3(I i) => i; static I F4(I i) => i; }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (4,42): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static I F1(I i) => i; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "i").WithArguments("I", "I").WithLocation(4, 42), // (5,42): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // static I F2(I i) => i; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "i").WithArguments("I", "I").WithLocation(5, 42)); } [Fact] public void Covariance_Delegate() { var source = @"delegate void D(T t); class C { static void F1(string s) { } static void F2(string? s) { } static void F3(object o) { } static void F4(object? o) { } static void F(D d) { } static void Main() { F(F1); F(F2); F(F3); F(F4); F(F1); // warning F(F2); F(F3); // warning F(F4); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (15,20): warning CS8622: Nullability of reference types in type of parameter 's' of 'void C.F1(string s)' doesn't match the target delegate 'D'. // F(F1); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F1").WithArguments("s", "void C.F1(string s)", "D").WithLocation(15, 20), // (17,20): warning CS8622: Nullability of reference types in type of parameter 'o' of 'void C.F3(object o)' doesn't match the target delegate 'D'. // F(F3); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "F3").WithArguments("o", "void C.F3(object o)", "D").WithLocation(17, 20)); } [Fact] public void Contravariance_Delegate() { var source = @"delegate T D(); class C { static string F1() => string.Empty; static string? F2() => string.Empty; static object F3() => string.Empty; static object? F4() => string.Empty; static T F(D d) => d(); static void Main() { F(F1); F(F2); // warning F(F3); F(F4); // warning F(F1); F(F2); F(F3); F(F4); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (12,19): warning CS8621: Nullability of reference types in return type of 'string? C.F2()' doesn't match the target delegate 'D'. // F(F2); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F2").WithArguments("string? C.F2()", "D").WithLocation(12, 19), // (14,19): warning CS8621: Nullability of reference types in return type of 'object? C.F4()' doesn't match the target delegate 'D'. // F(F4); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "F4").WithArguments("object? C.F4()", "D").WithLocation(14, 19)); } [Fact] public void TypeArgumentInference_01() { string source = @" class C { void Main() {} T M1(T? x) where T: class {throw new System.NotImplementedException();} void Test1(string? x1) { M1(x1).ToString(); } void Test2(string?[] x2) { M1(x2)[0].ToString(); } void Test3(CL0? x3) { M1(x3).P1.ToString(); } void Test11(string? x11) { M1(x11).ToString(); } void Test12(string?[] x12) { M1(x12)[0].ToString(); } void Test13(CL0? x13) { M1?>(x13).P1.ToString(); } } class CL0 { public T P1 {get;set;} } "; CSharpCompilation c = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); c.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // M1(x2)[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x2)[0]").WithLocation(15, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // M1(x3).P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x3).P1").WithLocation(20, 9), // (25,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.M1(T?)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // M1(x11).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("C.M1(T?)", "T", "string?").WithLocation(25, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // M1(x11).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x11)").WithLocation(25, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // M1(x12)[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x12)[0]").WithLocation(30, 9), // (35,9): warning CS8634: The type 'CL0?' cannot be used as type parameter 'T' in the generic type or method 'C.M1(T?)'. Nullability of type argument 'CL0?' doesn't match 'class' constraint. // M1?>(x13).P1.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1?>").WithArguments("C.M1(T?)", "T", "CL0?").WithLocation(35, 9), // (35,9): warning CS8602: Dereference of a possibly null reference. // M1?>(x13).P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1?>(x13)").WithLocation(35, 9), // (35,9): warning CS8602: Dereference of a possibly null reference. // M1?>(x13).P1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1?>(x13).P1").WithLocation(35, 9), // (41,14): warning CS8618: Non-nullable property 'P1' is uninitialized. // public T P1 {get;set;} Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "P1").WithArguments("property", "P1").WithLocation(41, 14) ); } [Fact] public void ExplicitImplementations_LazyMethodChecks() { var source = @"interface I { void M(T? x) where T : class; } class C : I { void I.M(T? x) { } }"; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (5,11): error CS0535: 'C' does not implement interface member 'I.M(T?)' // class C : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C", "I.M(T?)").WithLocation(5, 11), // (7,12): error CS0539: 'C.M(T?)' in explicit interface declaration is not found among members of the interface that can be implemented // void I.M(T? x) { } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M").WithArguments("C.M(T?)").WithLocation(7, 12), // (7,20): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // void I.M(T? x) { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("System.Nullable", "T", "T").WithLocation(7, 20)); var method = compilation.GetMember("C").GetMethod("I.M"); var implementations = method.ExplicitInterfaceImplementations; Assert.Empty(implementations); } [Fact] public void ExplicitImplementations_LazyMethodChecks_01() { var source = @"interface I { void M(T? x) where T : class; } class C : I { void I.M(T? x) where T : class{ } }"; var compilation = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var method = compilation.GetMember("C").GetMethod("I.M"); var implementations = method.ExplicitInterfaceImplementations; Assert.Equal(new[] { "void I.M(T? x)" }, implementations.SelectAsArray(m => m.ToTestDisplayString())); } [Fact] public void EmptyStructDifferentAssembly() { var sourceA = @"using System.Collections; public struct S { public S(string f, IEnumerable g) { F = f; G = g; } private string F { get; } private IEnumerable G { get; } }"; var compA = CreateCompilation(sourceA, parseOptions: TestOptions.Regular7); var sourceB = @"using System.Collections.Generic; class C { static void Main() { var c = new List(); c.Add(new S(string.Empty, new object[0])); } }"; var compB = CreateCompilation( sourceB, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular8, references: new[] { compA.EmitToImageReference() }); CompileAndVerify(compB, expectedOutput: ""); } [Fact] public void EmptyStructField() { var source = @"#pragma warning disable 8618 class A { } struct B { } struct S { public readonly A A; public readonly B B; public S(B b) : this(null, b) { } public S(A a, B b) { this.A = a; this.B = b; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (8,26): warning CS8625: Cannot convert null literal to non-nullable reference type. // public S(B b) : this(null, b) Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 26)); } [Fact] public void WarningOnConversion_Assignment() { var source = @"#pragma warning disable 8618 class Person { internal string FirstName { get; set; } internal string LastName { get; set; } internal string? MiddleName { get; set; } } class Program { static void F(Person p) { p.LastName = null; p.LastName = (string)null; p.LastName = (string?)null; p.LastName = null as string; p.LastName = null as string?; p.LastName = default(string); p.LastName = default; p.FirstName = p.MiddleName; p.LastName = p.MiddleName ?? null; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (12,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // p.LastName = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 22), // (13,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // p.LastName = (string)null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(13, 22), // (13,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // p.LastName = (string)null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string)null").WithLocation(13, 22), // (14,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // p.LastName = (string?)null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string?)null").WithLocation(14, 22), // (15,22): warning CS8601: Possible null reference assignment. // p.LastName = null as string; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "null as string").WithLocation(15, 22), // (16,30): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // p.LastName = null as string?; Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(16, 30), // (17,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // p.LastName = default(string); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(17, 22), // (18,22): warning CS8625: Cannot convert null literal to non-nullable reference type. // p.LastName = default; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(18, 22), // (19,23): warning CS8601: Possible null reference assignment. // p.FirstName = p.MiddleName; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "p.MiddleName").WithLocation(19, 23), // (20,22): warning CS8601: Possible null reference assignment. // p.LastName = p.MiddleName ?? null; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "p.MiddleName ?? null").WithLocation(20, 22) ); } [Fact] public void WarningOnConversion_Receiver() { var source = @"#pragma warning disable 8618 class Person { internal string FirstName { get; set; } internal string LastName { get; set; } internal string? MiddleName { get; set; } } class Program { static void F(Person p) { ((string)null).F(); ((string?)null).F(); (null as string).F(); (null as string?).F(); default(string).F(); ((p != null) ? p.MiddleName : null).F(); (p.MiddleName ?? null).F(); } } static class Extensions { internal static void F(this string s) { } }"; var comp = CreateCompilationWithMscorlib45(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,18): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // (null as string?).F(); Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(15, 18), // (12,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((string)null).F(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(12, 10), // (12,10): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((string)null).F(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string)null").WithLocation(12, 10), // (13,10): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((string?)null).F(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string?)null").WithLocation(13, 10), // (14,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. // (null as string).F(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "null as string").WithArguments("s", "void Extensions.F(string s)").WithLocation(14, 10), // (16,9): warning CS8625: Cannot convert null literal to non-nullable reference type. // default(string).F(); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(16, 9), // (17,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. // ((p != null) ? p.MiddleName : null).F(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(p != null) ? p.MiddleName : null").WithArguments("s", "void Extensions.F(string s)").WithLocation(17, 10), // (18,10): warning CS8602: Dereference of a possibly null reference. // (p.MiddleName ?? null).F(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p").WithLocation(18, 10), // (18,10): warning CS8604: Possible null reference argument for parameter 's' in 'void Extensions.F(string s)'. // (p.MiddleName ?? null).F(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p.MiddleName ?? null").WithArguments("s", "void Extensions.F(string s)").WithLocation(18, 10) ); } [Fact] public void WarningOnConversion_Argument() { var source = @"#pragma warning disable 8618 class Person { internal string FirstName { get; set; } internal string LastName { get; set; } internal string? MiddleName { get; set; } } class Program { static void F(Person p) { G(null); G((string)null); G((string?)null); G(null as string); G(null as string?); G(default(string)); G(default); G((p != null) ? p.MiddleName : null); G(p.MiddleName ?? null); } static void G(string name) { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (16,19): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // G(null as string?); Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(16, 19), // (12,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // G(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 11), // (13,11): warning CS8600: Converting null literal or possible null value to non-nullable type. // G((string)null); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(13, 11), // (13,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // G((string)null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string)null").WithLocation(13, 11), // (14,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // G((string?)null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string?)null").WithLocation(14, 11), // (15,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. // G(null as string); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "null as string").WithArguments("name", "void Program.G(string name)").WithLocation(15, 11), // (17,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // G(default(string)); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(17, 11), // (18,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // G(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(18, 11), // (19,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. // G((p != null) ? p.MiddleName : null); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(p != null) ? p.MiddleName : null").WithArguments("name", "void Program.G(string name)").WithLocation(19, 11), // (20,11): warning CS8602: Dereference of a possibly null reference. // G(p.MiddleName ?? null); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p").WithLocation(20, 11), // (20,11): warning CS8604: Possible null reference argument for parameter 'name' in 'void Program.G(string name)'. // G(p.MiddleName ?? null); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p.MiddleName ?? null").WithArguments("name", "void Program.G(string name)").WithLocation(20, 11) ); } [Fact] public void WarningOnConversion_Return() { var source = @"#pragma warning disable 8618 class Person { internal string FirstName { get; set; } internal string LastName { get; set; } internal string? MiddleName { get; set; } } class Program { static string F1() => null; static string F2() => (string)null; static string F3() => (string?)null; static string F4() => null as string; static string F5() => null as string?; static string F6() => default(string); static string F7() => default; static string F8(Person p) => (p != null) ? p.MiddleName : null; static string F9(Person p) => p.MiddleName ?? null; }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (10,27): warning CS8603: Possible null reference return. // static string F1() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(10, 27), // (11,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // static string F2() => (string)null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(11, 27), // (11,27): warning CS8603: Possible null reference return. // static string F2() => (string)null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(string)null").WithLocation(11, 27), // (12,27): warning CS8603: Possible null reference return. // static string F3() => (string?)null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(string?)null").WithLocation(12, 27), // (13,27): warning CS8603: Possible null reference return. // static string F4() => null as string; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null as string").WithLocation(13, 27), // (14,35): error CS8651: It is not legal to use nullable reference type 'string?' in an as expression; use the underlying type 'string' instead. // static string F5() => null as string?; Diagnostic(ErrorCode.ERR_AsNullableType, "string?").WithArguments("string").WithLocation(14, 35), // (15,27): warning CS8603: Possible null reference return. // static string F6() => default(string); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(string)").WithLocation(15, 27), // (16,27): warning CS8603: Possible null reference return. // static string F7() => default; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(16, 27), // (17,35): warning CS8603: Possible null reference return. // static string F8(Person p) => (p != null) ? p.MiddleName : null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(p != null) ? p.MiddleName : null").WithLocation(17, 35), // (18,35): warning CS8603: Possible null reference return. // static string F9(Person p) => p.MiddleName ?? null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "p.MiddleName ?? null").WithLocation(18, 35) ); } [Fact] public void SuppressNullableWarning() { var source = @"class C { static void F(string? s) // 1 { G(null!); // 2, 3 G((null as string)!); // 4, 5 G(default(string)!); // 6, 7 G(default!); // 8, 9, 10 G(s!); // 11, 12 } static void G(string s) { } }"; var comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular7, skipUsesIsNullable: true); comp.VerifyDiagnostics( // (5,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(null!); // 2, 3 Diagnostic(ErrorCode.ERR_FeatureInPreview, "null!").WithArguments("nullable reference types").WithLocation(5, 11), // (6,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G((null as string)!); // 4, 5 Diagnostic(ErrorCode.ERR_FeatureInPreview, "(null as string)!").WithArguments("nullable reference types").WithLocation(6, 11), // (7,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(default(string)!); // 6, 7 Diagnostic(ErrorCode.ERR_FeatureInPreview, "default(string)!").WithArguments("nullable reference types").WithLocation(7, 11), // (8,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(default!); // 8, 9, 10 Diagnostic(ErrorCode.ERR_FeatureInPreview, "default!").WithArguments("nullable reference types").WithLocation(8, 11), // (8,11): error CS8107: Feature 'default literal' is not available in C# 7.0. Please use language version 7.1 or greater. // G(default!); // 8, 9, 10 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "default").WithArguments("default literal", "7.1").WithLocation(8, 11), // (9,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(s!); // 11, 12 Diagnostic(ErrorCode.ERR_FeatureInPreview, "s!").WithArguments("nullable reference types").WithLocation(9, 11), // (3,25): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // static void F(string? s) // 1 Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(3, 25) ); comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void SuppressNullableWarning_ReferenceType() { var source = @"class C { static C F(C? o) { C other; other = o!; o = other; o!.F(); G(o!); return o!; } void F() { } static void G(C o) { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_Array() { var source = @"class C { static object[] F(object?[] o) { object[] other; other = o!; o = other!; o!.F(); G(o!); return o!; } static void G(object[] o) { } } static class E { internal static void F(this object[] o) { } }"; var comp = CreateCompilationWithMscorlib45( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_ConstructedType() { var source = @"class C { static C F(C o) { C other; other = o!; // 1 o = other!; // 2 o!.F(); G(o!); // 3 return o!; // 4 } static void G(C o) { } } class C { internal void F() { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29902, "https://github.com/dotnet/roslyn/issues/29902")] public void SuppressNullableWarning_Multiple() { var source = @"class C { static void F(string? s) { G(default!!); G(s!!); G((s!)!); } static void G(string s) { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void SuppressNullableWarning_Nested() { var source = @"class C where T : class { static T? F(T t) => t; static T? G(T t) => t; static void M(T? t) { F(G(t!)); F(G(t)!); F(G(t!)!); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (7,11): warning CS8604: Possible null reference argument for parameter 't' in 'T? C.F(T t)'. // F(G(t!)); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "G(t!)").WithArguments("t", "T? C.F(T t)").WithLocation(7, 11), // (8,13): warning CS8604: Possible null reference argument for parameter 't' in 'T? C.G(T t)'. // F(G(t)!); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t").WithArguments("t", "T? C.G(T t)").WithLocation(8, 13)); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_Conditional() { var source = @"class C { } class C { static void F(C? x, C y, bool c) { C a; a = c ? x : y; // 1 a = c ? y : x; // 2 a = c ? x : y!; // 3 a = c ? x! : y; // 4 a = c ? x! : y!; C b; b = c ? x : y; // 5 b = c ? x : y!; // 6 b = c ? x! : y; // 7 b = c ? x! : y!; // 8 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // a = c ? x : y; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c ? x : y").WithLocation(7, 13), // (7,21): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // a = c ? x : y; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(7, 21), // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // a = c ? y : x; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c ? y : x").WithLocation(8, 13), // (8,17): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // a = c ? y : x; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 17), // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // a = c ? x : y!; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c ? x : y!").WithLocation(9, 13), // (10,22): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // a = c ? x! : y; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(10, 22), // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // b = c ? x : y; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c ? x : y").WithLocation(13, 13), // (13,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = c ? x : y; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x : y").WithArguments("C", "C").WithLocation(13, 13), // (13,21): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = c ? x : y; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(13, 21), // (14,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // b = c ? x : y!; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c ? x : y!").WithLocation(14, 13), // (14,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = c ? x : y!; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x : y!").WithArguments("C", "C").WithLocation(14, 13), // (15,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = c ? x! : y; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x! : y").WithArguments("C", "C").WithLocation(15, 13), // (15,22): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = c ? x! : y; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(15, 22), // (16,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = c ? x! : y!; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c ? x! : y!").WithArguments("C", "C").WithLocation(16, 13) ); } [Fact] public void SuppressNullableWarning_NullCoalescing() { var source = @" class C { static void F(C? x, C y) { var t1 = x ?? y; // 1 var t2 = y ?? x; // 2 var t3 = x! ?? y; // 3 var t4 = y! ?? x; // 4 var t5 = x ?? y!; var t6 = y ?? x!; var t7 = x! ?? y!; var t8 = y! ?? x!; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,23): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var t1 = x ?? y; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(6, 23), // (7,23): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var t2 = y ?? x; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(7, 23), // (8,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var t3 = x! ?? y; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 24), // (9,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var t4 = y! ?? x; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(9, 24)); } [Fact] [WorkItem(30151, "https://github.com/dotnet/roslyn/issues/30151")] [WorkItem(33346, "https://github.com/dotnet/roslyn/issues/33346")] public void SuppressNullableWarning_ArrayInitializer() { var source = @" class C { static void F(C? x, C y) { var a1 = new[] { x, y }; // 1 _ = a1 /*T:C?[]!*/; var a2 = new[] { x!, y }; // 2 _ = a2 /*T:C![]!*/; var a3 = new[] { x, y! }; _ = a3 /*T:C?[]!*/; var a4 = new[] { x!, y! }; _ = a4 /*T:C![]!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (6,29): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var a1 = new[] { x, y }; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(6, 29), // (8,30): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var a2 = new[] { x!, y }; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 30)); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_LocalDeclaration() { var source = @" class C { static void F(C? x, C y) { C? c1 = y; // 1 C c2 = x; // 2 and 3 C? c3 = y!; // 4 C c4 = x!; // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,25): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // C? c1 = y; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(6, 25), // (7,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // C c2 = x; // 2 and 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 25), // (7,25): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // C c2 = x; // 2 and 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(7, 25) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_Cast() { var source = @" class C { static void F(C? x, C y) { var c1 = (C?)y; var c2 = (C)x; // warn var c3 = (C?)y!; var c4 = (C)x!; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var c1 = (C?)y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(C?)y").WithArguments("C", "C").WithLocation(6, 18), // (7,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // var c2 = (C)x; // warn Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)x").WithLocation(7, 18), // (7,18): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // var c2 = (C)x; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(C)x").WithArguments("C", "C").WithLocation(7, 18) ); } [Fact] public void SuppressNullableWarning_ObjectInitializer() { var source = @" class C { public C? X = null!; public C Y = null!; static void F(C? x, C y) { _ = new C() { X = y, Y = x }; _ = new C() { X = y!, Y = x! }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,32): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // _ = new C() { X = y, Y = x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(8, 32), // (8,39): warning CS8601: Possible null reference assignment. // _ = new C() { X = y, Y = x }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(8, 39), // (8,39): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // _ = new C() { X = y, Y = x }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(8, 39) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_CollectionInitializer() { var source = @" using System.Collections; class C : IEnumerable { IEnumerator IEnumerable.GetEnumerator() => throw null!; void Add(C key, params C[] value) => throw null!; static void F(C? x) { _ = new C() { x, x }; // warn 1 and 2 _ = new C() { x!, x! }; // warn 3 and 4 } } class D : IEnumerable { IEnumerator IEnumerable.GetEnumerator() => throw null!; void Add(D? key, params D?[] value) => throw null!; static void F(D y) { _ = new D() { y, y }; // warn 5 and 6 _ = new D() { y!, y! }; // warn 7 and 8 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,28): warning CS8620: Nullability of reference types in argument of type 'D' doesn't match target type 'D' for parameter 'key' in 'void D.Add(D? key, params D?[] value)'. // _ = new D() { y, y }; // warn 5 and 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("D", "D", "key", "void D.Add(D? key, params D?[] value)").WithLocation(19, 28), // (19,32): warning CS8620: Nullability of reference types in argument of type 'D' doesn't match target type 'D' for parameter 'key' in 'void D.Add(D? key, params D?[] value)'. // _ = new D() { y, y }; // warn 5 and 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("D", "D", "key", "void D.Add(D? key, params D?[] value)").WithLocation(19, 32), // (9,28): warning CS8604: Possible null reference argument for parameter 'key' in 'void C.Add(C key, params C[] value)'. // _ = new C() { x, x }; // warn 1 and 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("key", "void C.Add(C key, params C[] value)").WithLocation(9, 28), // (9,28): warning CS8620: Nullability of reference types in argument of type 'C' doesn't match target type 'C' for parameter 'key' in 'void C.Add(C key, params C[] value)'. // _ = new C() { x, x }; // warn 1 and 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("C", "C", "key", "void C.Add(C key, params C[] value)").WithLocation(9, 28), // (9,31): warning CS8604: Possible null reference argument for parameter 'key' in 'void C.Add(C key, params C[] value)'. // _ = new C() { x, x }; // warn 1 and 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("key", "void C.Add(C key, params C[] value)").WithLocation(9, 31), // (9,31): warning CS8620: Nullability of reference types in argument of type 'C' doesn't match target type 'C' for parameter 'key' in 'void C.Add(C key, params C[] value)'. // _ = new C() { x, x }; // warn 1 and 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("C", "C", "key", "void C.Add(C key, params C[] value)").WithLocation(9, 31) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_IdentityConversion() { var source = @"class C { } class C { static void F(C x, C y) { C a; a = x; // 1 a = x!; // 2 C b; b = y; // 3 b = y!; // 4 } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (7,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // a = x; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "C").WithLocation(7, 13), // (10,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // b = y; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "C").WithLocation(10, 13) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_ImplicitConversion() { var source = @"interface I { } class C : I { } class C { static void F(C x, C y) { I a; a = x; a = x!; I b; b = y; b = y!; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (8,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'I'. // a = x; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("C", "I").WithLocation(8, 13), // (11,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'I'. // b = y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "I").WithLocation(11, 13) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_ImplicitExtensionMethodThisConversion() { var source = @"interface I { } class C : I { } class C { static void F(C x, C y) { x.F1(); x!.F1(); y.F2(); y!.F2(); } } static class E { internal static void F1(this I o) { } internal static void F2(this I o) { } }"; var comp = CreateCompilationWithMscorlib45( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (7,9): warning CS8620: Nullability of reference types in argument of type 'C' doesn't match target type 'I' for parameter 'o' in 'void E.F1(I o)'. // x.F1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("C", "I", "o", "void E.F1(I o)").WithLocation(7, 9), // (9,9): warning CS8620: Nullability of reference types in argument of type 'C' doesn't match target type 'I' for parameter 'o' in 'void E.F2(I o)'. // y.F2(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "I", "o", "void E.F2(I o)").WithLocation(9, 9) ); } [Fact] public void SuppressNullableWarning_ImplicitUserDefinedConversion() { var source = @"class A { } class B { public static implicit operator A(B b) => new A(); } class C { static void F(B b1, B b2) { A a1; a1 = b1; // 1 a1 = b1!; // 2 A a2; a2 = b2; // 3 a2 = b2!; // 4 } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (11,14): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // a1 = b1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b1").WithArguments("A", "A").WithLocation(11, 14), // (14,14): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // a2 = b2; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b2").WithArguments("A", "A").WithLocation(14, 14) ); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_ExplicitConversion() { var source = @"interface I { } class C { } class C { static void F(C x, C y) { I a; a = (I)x; // 1 a = ((I)x)!; // 2 I b; b = (I)y; // 3 b = ((I)y)!; // 4 } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (8,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // a = (I)x; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(I)x").WithArguments("I", "I").WithLocation(8, 13), // (11,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // b = (I)y; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(I)y").WithArguments("I", "I").WithLocation(11, 13) ); } [Fact] public void SuppressNullableWarning_Ref() { var source = @"class C { static void F(ref string s, ref string? t) { } static void Main() { string? s = null; string t = """"; F(ref s, ref t); F(ref s!, ref t!); } }"; var comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue(TestOptions.ReleaseExe)); comp.VerifyDiagnostics( // (10,15): warning CS8601: Possible null reference assignment. // F(ref s, ref t); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s").WithLocation(10, 15), // (10,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(ref s, ref t); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(10, 22)); } [Fact] public void SuppressNullableWarning_Ref_WithNestedDifferences() { var source = @" class List { } class C { static void F(ref List a, ref List? b, ref List c, ref List? d) { } static void F1(ref List a, ref List? b, ref List c, ref List? d) { F(ref b, ref c, ref d, ref a); // warnings } static void F2(ref List a, ref List? b, ref List c, ref List? d) { F(ref b!, ref c!, ref d!, ref a!); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (10,15): warning CS8601: Possible null reference assignment. // F(ref b, ref c, ref d, ref a); // warnings Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "b").WithLocation(10, 15), // (10,22): warning CS8620: Argument of type 'List' cannot be used for parameter 'b' of type 'List' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); // warnings Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "c").WithArguments("List", "List", "b", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 22), // (10,22): warning CS8601: Possible null reference assignment. // F(ref b, ref c, ref d, ref a); // warnings Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c").WithLocation(10, 22), // (10,29): warning CS8601: Possible null reference assignment. // F(ref b, ref c, ref d, ref a); // warnings Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "d").WithLocation(10, 29), // (10,36): warning CS8620: Argument of type 'List' cannot be used for parameter 'd' of type 'List' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); // warnings Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(10, 36), // (10,36): warning CS8601: Possible null reference assignment. // F(ref b, ref c, ref d, ref a); // warnings Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "a").WithLocation(10, 36)); } [Fact] public void SuppressNullableWarning_Ref_WithUnassignedLocals() { var source = @" class List { } class C { static void F(ref List a, ref List? b, ref List c, ref List? d) { throw null!; } static void F1() { List a; List? b; List c; List? d; F(ref b, ref c, ref d, ref a); } static void F2() { List a; List? b; List c; List? d; F(ref b!, ref c!, ref d!, ref a!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,15): error CS0165: Use of unassigned local variable 'b' // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.ERR_UseDefViolation, "b").WithArguments("b").WithLocation(15, 15), // (15,22): error CS0165: Use of unassigned local variable 'c' // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.ERR_UseDefViolation, "c").WithArguments("c").WithLocation(15, 22), // (15,22): warning CS8620: Argument of type 'List' cannot be used for parameter 'b' of type 'List' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "c").WithArguments("List", "List", "b", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(15, 22), // (15,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c").WithLocation(15, 22), // (15,29): error CS0165: Use of unassigned local variable 'd' // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.ERR_UseDefViolation, "d").WithArguments("d").WithLocation(15, 29), // (15,36): error CS0165: Use of unassigned local variable 'a' // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.ERR_UseDefViolation, "a").WithArguments("a").WithLocation(15, 36), // (15,36): warning CS8620: Argument of type 'List' cannot be used for parameter 'd' of type 'List' in 'void C.F(ref List a, ref List? b, ref List c, ref List? d)' due to differences in the nullability of reference types. // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "a").WithArguments("List", "List", "d", "void C.F(ref List a, ref List? b, ref List c, ref List? d)").WithLocation(15, 36), // (15,36): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(ref b, ref c, ref d, ref a); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "a").WithLocation(15, 36), // (23,15): error CS0165: Use of unassigned local variable 'b' // F(ref b!, ref c!, ref d!, ref a!); Diagnostic(ErrorCode.ERR_UseDefViolation, "b").WithArguments("b").WithLocation(23, 15), // (23,23): error CS0165: Use of unassigned local variable 'c' // F(ref b!, ref c!, ref d!, ref a!); Diagnostic(ErrorCode.ERR_UseDefViolation, "c").WithArguments("c").WithLocation(23, 23), // (23,31): error CS0165: Use of unassigned local variable 'd' // F(ref b!, ref c!, ref d!, ref a!); Diagnostic(ErrorCode.ERR_UseDefViolation, "d").WithArguments("d").WithLocation(23, 31), // (23,39): error CS0165: Use of unassigned local variable 'a' // F(ref b!, ref c!, ref d!, ref a!); Diagnostic(ErrorCode.ERR_UseDefViolation, "a").WithArguments("a").WithLocation(23, 39) ); } [Fact] public void SuppressNullableWarning_Out_WithNestedDifferences() { var source = @" class List { } class C { static void F(out List a, out List? b, out List c, out List? d) { throw null!; } static void F1(out List a, out List? b, out List c, out List? d) { F(out b, out c, out d, out a); // warn on `c` and `a` } static void F2(out List a, out List? b, out List c, out List? d) { F(out b!, out c!, out d!, out a!); // warn on `c!` and `a!` } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (11,22): warning CS8601: Possible null reference assignment. // F(out b, out c, out d, out a); // warn on `c` and `a` Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c").WithLocation(11, 22), // (11,22): warning CS8624: Argument of type 'List' cannot be used as an output of type 'List' for parameter 'b' in 'void C.F(out List a, out List? b, out List c, out List? d)' due to differences in the nullability of reference types. // F(out b, out c, out d, out a); // warn on `c` and `a` Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "c").WithArguments("List", "List", "b", "void C.F(out List a, out List? b, out List c, out List? d)").WithLocation(11, 22), // (11,36): warning CS8601: Possible null reference assignment. // F(out b, out c, out d, out a); // warn on `c` and `a` Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "a").WithLocation(11, 36), // (11,36): warning CS8624: Argument of type 'List' cannot be used as an output of type 'List' for parameter 'd' in 'void C.F(out List a, out List? b, out List c, out List? d)' due to differences in the nullability of reference types. // F(out b, out c, out d, out a); // warn on `c` and `a` Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "a").WithArguments("List", "List", "d", "void C.F(out List a, out List? b, out List c, out List? d)").WithLocation(11, 36) ); } [Fact] [WorkItem(27522, "https://github.com/dotnet/roslyn/issues/27522")] public void SuppressNullableWarning_Out() { var source = @"class C { static void F(out string s, out string? t) { s = string.Empty; t = string.Empty; } static ref string RefReturn() => ref (new string[1])[0]; static void Main() { string? s; string t; F(out s, out t); // warn F(out s!, out t!); // ok F(out RefReturn(), out RefReturn()); // warn F(out RefReturn()!, out RefReturn()!); // ok F(out (s!), out (t!)); // errors F(out (s)!, out (t)!); // errors } }"; var comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue(TestOptions.ReleaseExe)); comp.VerifyDiagnostics( // (18,19): error CS1525: Invalid expression term ',' // F(out (s)!, out (t)!); // errors Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(18, 19), // (18,29): error CS1525: Invalid expression term ')' // F(out (s)!, out (t)!); // errors Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(18, 29), // (18,16): error CS0118: 's' is a variable but is used like a type // F(out (s)!, out (t)!); // errors Diagnostic(ErrorCode.ERR_BadSKknown, "s").WithArguments("s", "variable", "type").WithLocation(18, 16), // (18,26): error CS0118: 't' is a variable but is used like a type // F(out (s)!, out (t)!); // errors Diagnostic(ErrorCode.ERR_BadSKknown, "t").WithArguments("t", "variable", "type").WithLocation(18, 26), // (13,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(out s, out t); // warn Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(13, 22), // (15,32): warning CS8601: Possible null reference assignment. // F(out RefReturn(), out RefReturn()); // warn Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "RefReturn()").WithLocation(15, 32)); } [Fact] [WorkItem(27317, "https://github.com/dotnet/roslyn/pull/27317")] public void RefOutSuppressionInference() { var src = @" class C { void M(ref T t) { } void M2(out T t) => throw null!; void M3(in T t) { } T M4(in T t) => t; void M3() { string? s1 = null; M(ref s1!); s1.ToString(); string? s2 = null; M2(out s2!); s2.ToString(); string? s3 = null; M3(s3!); s3.ToString(); // warn string? s4 = null; M3(in s4!); s4.ToString(); // warn string? s5 = null; s5 = M4(s5!); s5.ToString(); string? s6 = null; s6 = M4(in s6!); s6.ToString(); } }"; var comp = CreateCompilation(src, options: WithNonNullTypesTrue(TestOptions.DebugDll)); comp.VerifyDiagnostics( // (21,9): warning CS8602: Dereference of a possibly null reference. // s3.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s3").WithLocation(21, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(25, 9)); } [Fact] [WorkItem(27522, "https://github.com/dotnet/roslyn/issues/27522")] [WorkItem(29903, "https://github.com/dotnet/roslyn/issues/29903")] public void SuppressNullableWarning_Assignment() { var source = @"class C { static void Main() { string? s = null; string t = string.Empty; t! = s; t! += s; (t!) = s; } }"; var comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue(TestOptions.ReleaseExe)); comp.VerifyDiagnostics( // (7,9): error CS8598: The suppression operator is not allowed in this context // t! = s; Diagnostic(ErrorCode.ERR_IllegalSuppression, "t").WithLocation(7, 9), // (7,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t! = s; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(7, 14), // (8,9): error CS8598: The suppression operator is not allowed in this context // t! += s; Diagnostic(ErrorCode.ERR_IllegalSuppression, "t").WithLocation(8, 9), // (9,10): error CS8598: The suppression operator is not allowed in this context // (t!) = s; Diagnostic(ErrorCode.ERR_IllegalSuppression, "t").WithLocation(9, 10), // (9,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // (t!) = s; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s").WithLocation(9, 16) ); } [Fact] public void SuppressNullableWarning_Conversion() { var source = @"class A { public static implicit operator B(A a) => new B(); } class B { } class C { static void F(A? a) { G((B)a); G((B)a!); } static void G(B b) { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (12,14): warning CS8604: Possible null reference argument for parameter 'a' in 'A.implicit operator B(A a)'. // G((B)a); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a").WithArguments("a", "A.implicit operator B(A a)").WithLocation(12, 14)); } [Fact] [WorkItem(29906, "https://github.com/dotnet/roslyn/issues/29906")] public void SuppressNullableWarning_Condition() { var source = @"class C { static object? F(bool b) { return (b && G(out var o))! ? o : null; } static bool G(out object o) { o = new object(); return true; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Deconstruction() { var source = @" class C { } class C2 { void M(C c) { // line 1 (string d1, (C d2, string d3)) = (null, (c, null)); // line 2 (string e1, (C e2, string e3)) = (null, (c, null))!; // line 3 (string f1, (C f2, string f3)) = (null, (c, null)!); // line 4 (string g1, (C g2, string g3)) = (null!, (c, null)!); // line 5 (string h1, (C h2, string h3)) = (null!, (c!, null!)); // no warnings // line 6 (string i1, (C i2, string i3)) = default((string, (C, string)))!; // line 7 (string j1, (C j2, string j3)) = (null, default((C, string))!); // line 8 (string k1, (C k2, string k3)) = (null!, default((C, string))!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // line 1 // (10,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string d1, (C d2, string d3)) = (null, (c, null)); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 51), // (10,58): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // (string d1, (C d2, string d3)) = (null, (c, null)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c").WithArguments("C", "C").WithLocation(10, 58), // (10,61): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string d1, (C d2, string d3)) = (null, (c, null)); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 61), // line 2 // (13,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string e1, (C e2, string e3)) = (null, (c, null))!; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 51), // (13,58): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // (string e1, (C e2, string e3)) = (null, (c, null))!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c").WithArguments("C", "C").WithLocation(13, 58), // (13,61): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string e1, (C e2, string e3)) = (null, (c, null))!; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 61), // line 3 // (16,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string f1, (C f2, string f3)) = (null, (c, null)!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(16, 51), // (16,58): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // (string f1, (C f2, string f3)) = (null, (c, null)!); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c").WithArguments("C", "C").WithLocation(16, 58), // (16,61): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string f1, (C f2, string f3)) = (null, (c, null)!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(16, 61), // line 4 // (19,59): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // (string g1, (C g2, string g3)) = (null!, (c, null)!); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c").WithArguments("C", "C").WithLocation(19, 59), // (19,62): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string g1, (C g2, string g3)) = (null!, (c, null)!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(19, 62), // line 6 // (25,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string i1, (C i2, string i3)) = default((string, (C, string)))!; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((string, (C, string)))").WithLocation(25, 50), // (25,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string i1, (C i2, string i3)) = default((string, (C, string)))!; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((string, (C, string)))").WithLocation(25, 50), // (25,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string i1, (C i2, string i3)) = default((string, (C, string)))!; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((string, (C, string)))").WithLocation(25, 50), // line 7 // (28,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string j1, (C j2, string j3)) = (null, default((C, string))!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(28, 51), // (28,57): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string j1, (C j2, string j3)) = (null, default((C, string))!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((C, string))").WithLocation(28, 57), // (28,57): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string j1, (C j2, string j3)) = (null, default((C, string))!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((C, string))").WithLocation(28, 57), // line 8 // (31,58): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string k1, (C k2, string k3)) = (null!, default((C, string))!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((C, string))").WithLocation(31, 58), // (31,58): warning CS8600: Converting null literal or possible null value to non-nullable type. // (string k1, (C k2, string k3)) = (null!, default((C, string))!); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((C, string))").WithLocation(31, 58) ); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_Tuple() { var source = @" class C { } class C2 { static T Id(T t) => t; void M(C c) { // line 1 (string, (C, string)) t1 = (null, (c, null)); t1.Item1.ToString(); // warn Id(t1).Item1.ToString(); // no warn // line 2 (string, (C, string)) t2 = (null, (c, null))!; t2.Item1.ToString(); // warn Id(t2).Item1.ToString(); // no warn // line 3 (string, (C, string)) t3 = (null, (c, null)!); t3.Item1.ToString(); // warn Id(t3).Item1.ToString(); // no warn // line 4 (string, (C, string)) t4 = (null, (c, null)!)!; // no warn t4.Item1.ToString(); // warn Id(t4).Item1.ToString(); // no warn // line 5 (string, (C, string)) t5 = (null!, (c, null)!); // no warn t5.Item1.ToString(); // no warn Id(t5).Item1.ToString(); // no warn // line 6 (string, (C, string)) t6 = (null!, (c!, null!)); // warn t6.Item1.ToString(); // no warn Id(t6).Item1.ToString(); // no warn // line 7 (string, (C, string)) t7 = (null!, (c!, null!)!); // no warn t7.Item1.ToString(); // no warn Id(t7).Item1.ToString(); // no warn // line 8 (string, (C, string)) t8 = (null, (c, null))!; // warn t8.Item1.ToString(); // warn Id(t8).Item1.ToString(); // no warn } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // line 1 // (9,51): warning CS8619: Nullability of reference types in value of type '(C c, string?)' doesn't match target type '(C, string)'. // (string, (C, string)) t1 = (null, (c, null)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(c, null)").WithArguments("(C c, string?)", "(C, string)").WithLocation(9, 51), // (9,44): warning CS8619: Nullability of reference types in value of type '(string?, (C, string))' doesn't match target type '(string, (C, string))'. // (string, (C, string)) t1 = (null, (c, null)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, (c, null))").WithArguments("(string?, (C, string))", "(string, (C, string))").WithLocation(9, 44), // (10,9): warning CS8602: Dereference of a possibly null reference. // t1.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1.Item1").WithLocation(10, 9), // line 2 // (14,51): warning CS8619: Nullability of reference types in value of type '(C c, string?)' doesn't match target type '(C, string)'. // (string, (C, string)) t2 = (null, (c, null))!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(c, null)").WithArguments("(C c, string?)", "(C, string)").WithLocation(14, 51), // (15,9): warning CS8602: Dereference of a possibly null reference. // t2.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2.Item1").WithLocation(15, 9), // line 3 // (19,44): warning CS8619: Nullability of reference types in value of type '(string?, (C, string))' doesn't match target type '(string, (C, string))'. // (string, (C, string)) t3 = (null, (c, null)!); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, (c, null)!)").WithArguments("(string?, (C, string))", "(string, (C, string))").WithLocation(19, 44), // (20,9): warning CS8602: Dereference of a possibly null reference. // t3.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3.Item1").WithLocation(20, 9), // line 4 // (25,9): warning CS8602: Dereference of a possibly null reference. // t4.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4.Item1").WithLocation(25, 9), // line 6 // (34,52): warning CS8619: Nullability of reference types in value of type '(C, string)' doesn't match target type '(C, string)'. // (string, (C, string)) t6 = (null!, (c!, null!)); // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(c!, null!)").WithArguments("(C, string)", "(C, string)").WithLocation(34, 52), // line 8 // (44,51): warning CS8619: Nullability of reference types in value of type '(C c, string?)' doesn't match target type '(C, string)'. // (string, (C, string)) t8 = (null, (c, null))!; // warn Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(c, null)").WithArguments("(C c, string?)", "(C, string)").WithLocation(44, 51), // (45,9): warning CS8602: Dereference of a possibly null reference. // t8.Item1.ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t8.Item1").WithLocation(45, 9)); CompileAndVerify(comp); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_TupleEquality() { var source = @"class C { static void M((string, C) t, C c) { _ = t == (null, c); _ = t == (null, c)!; _ = (1, t) == (1, (null, c)); _ = (1, t) == (1, (null, c)!); _ = (1, t) == (1, (null!, c!)); _ = (1, t!) == (1, (null, c)); _ = (t, (null, c)!) == ((null, c)!, t); _ = (t, (null!, c!)) == ((null!, c!), t); _ = (t!, (null, c)) == ((null, c), t!); _ = (t, (null, c))! == ((null, c), t); _ = (t, (null, c)) == ((null, c), t)!; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); CompileAndVerify(comp); } [Fact] public void SuppressNullableWarning_ValueType_01() { var source = @"struct S { static void F() { G(1!); G(((int?)null)!); G(default(S)!); _ = new S2()!; } static void G(object o) { } static void G(T? t) where T : struct { } } struct S2 { }"; // Feature enabled. var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); // Feature disabled. comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); // Feature disabled (C# 7). comp = CreateCompilation( new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics( // (5,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(1!); Diagnostic(ErrorCode.ERR_FeatureInPreview, "1!").WithArguments("nullable reference types").WithLocation(5, 11), // (6,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(((int?)null)!); Diagnostic(ErrorCode.ERR_FeatureInPreview, "((int?)null)!").WithArguments("nullable reference types").WithLocation(6, 11), // (7,11): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // G(default(S)!); Diagnostic(ErrorCode.ERR_FeatureInPreview, "default(S)!").WithArguments("nullable reference types").WithLocation(7, 11), // (8,13): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = new S2()!; Diagnostic(ErrorCode.ERR_FeatureInPreview, "new S2()!").WithArguments("nullable reference types").WithLocation(8, 13)); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_ValueType_02() { var source = @"struct S where T : class? { static S F(S s) => s /*T:S*/ !; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_UserDefinedConversion() { var source = @" struct S { public static implicit operator C?(S s) => new C(); } class C { void M() { C c = new S()!; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(29642, "https://github.com/dotnet/roslyn/issues/29642")] public void SuppressNullableWarning_UserDefinedConversion_InArrayInitializer() { var source = @" struct S { public static implicit operator C?(S s) => new C(); } class C { void M(C c) { var a = new[] { c, new S()! }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void SuppressNullableWarning_GenericType() { var source = @"struct S { static void F(TStruct tStruct, TRef tRef, TUnconstrained tUnconstrained) where TStruct : struct where TRef : class { _ = tStruct!; _ = tRef!; _ = tUnconstrained!; } }"; // Feature enabled. var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); // Feature disabled. comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); // Feature disabled (C# 7). comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics( // (6,13): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = tStruct!; Diagnostic(ErrorCode.ERR_FeatureInPreview, "tStruct!").WithArguments("nullable reference types").WithLocation(6, 13), // (7,13): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = tRef!; Diagnostic(ErrorCode.ERR_FeatureInPreview, "tRef!").WithArguments("nullable reference types").WithLocation(7, 13), // (8,13): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // _ = tUnconstrained!; Diagnostic(ErrorCode.ERR_FeatureInPreview, "tUnconstrained!").WithArguments("nullable reference types").WithLocation(8, 13) ); } [Fact] public void SuppressNullableWarning_TypeParameters_01() { var source = @"class C { static void F1(T1 t1) { default(T1).ToString(); // 1 default(T1)!.ToString(); t1.ToString(); // 2 t1!.ToString(); } static void F2(T2 t2) where T2 : class { default(T2).ToString(); // 3 default(T2)!.ToString(); // 4 t2.ToString(); t2!.ToString(); } static void F3(T3 t3) where T3 : struct { default(T3).ToString(); default(T3)!.ToString(); t3.ToString(); t3!.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // default(T1).ToString(); // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T1)").WithArguments("T1").WithLocation(5, 9), // (5,9): warning CS8602: Dereference of a possibly null reference. // default(T1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T1)").WithLocation(5, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // t1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(7, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // default(T2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T2)").WithLocation(12, 9) ); } [Fact] public void SuppressNullableWarning_TypeParameters_02() { var source = @"abstract class A { internal abstract void F(out T t, out U u) where U : T; } class B1 : A where T : class { internal override void F(out T t1, out U u1) { t1 = default(T)!; t1 = default!; u1 = default(U)!; u1 = default!; } } class B2 : A where T : struct { internal override void F(out T t2, out U u2) { t2 = default(T)!; // 1 t2 = default!; // 2 u2 = default(U)!; // 3 u2 = default!; // 4 } } class B3 : A { internal override void F(out T t3, out U u3) { t3 = default(T)!; t3 = default!; u3 = default(U)!; u3 = default!; } } class B4 : A { internal override void F(out object t4, out U u4) { t4 = default(object)!; t4 = default!; u4 = default(U)!; u4 = default!; } } class B5 : A { internal override void F(out int t5, out U u5) { t5 = default(int)!; // 5 t5 = default!; // 6 u5 = default(U)!; // 7 u5 = default!; // 8 } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); // https://github.com/dotnet/roslyn/issues/29907: Report error for `default!`. comp.VerifyDiagnostics(); } [Fact] public void SuppressNullableWarning_NonNullOperand() { var source = @"class C { static void F(string? s) { G(""""!); G((new string('a', 1))!); G((s ?? """")!); } static void G(string s) { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void SuppressNullableWarning_InvalidOperand() { var source = @"class C { static void F(C c) { G(F!); G(c.P!); } static void G(object o) { } object P { set { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,11): error CS1503: Argument 1: cannot convert from 'method group' to 'object' // G(F!); Diagnostic(ErrorCode.ERR_BadArgType, "F").WithArguments("1", "method group", "object").WithLocation(5, 11), // (6,11): error CS0154: The property or indexer 'C.P' cannot be used in this context because it lacks the get accessor // G(c.P!); Diagnostic(ErrorCode.ERR_PropertyLacksGet, "c.P").WithArguments("C.P").WithLocation(6, 11) ); } [Fact] public void SuppressNullableWarning_InvalidArrayInitializer() { var source = @"class C { static void F() { var a = new object[] { new object(), F! }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,46): error CS0428: Cannot convert method group 'F' to non-delegate type 'object'. Did you intend to invoke the method? // var a = new object[] { new object(), F! }; Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "F").WithArguments("F", "object").WithLocation(5, 46)); } [Fact, WorkItem(31370, "https://github.com/dotnet/roslyn/issues/31370")] public void SuppressNullableWarning_IndexedProperty() { var source0 = @"Imports System Imports System.Runtime.InteropServices Public Class A Public ReadOnly Property P(i As Integer) As Object Get Return Nothing End Get End Property Public ReadOnly Property Q(Optional i As Integer = 0) As Object Get Return Nothing End Get End Property End Class"; var ref0 = BasicCompilationUtils.CompileToMetadata(source0); var source = @"class B { static object F(A a, int i) { if (i > 0) { return a.P!; } return a.Q!; } }"; var comp = CreateCompilation( new[] { source }, new[] { ref0 }, parseOptions: TestOptions.Regular8, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,20): error CS0856: Indexed property 'A.P' has non-optional arguments which must be provided // return a.P!; Diagnostic(ErrorCode.ERR_IndexedPropertyRequiresParams, "a.P").WithArguments("A.P").WithLocation(7, 20)); } [Fact] public void LocalTypeInference() { var source = @"class C { static void F(string? s, string? t) { if (s != null) { var x = s; G(x); // no warning x = t; } else { var y = s; G(y); // warning y = t; } } static void G(string s) { } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = t; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(9, 17), // (14,15): warning CS8604: Possible null reference argument for parameter 's' in 'void C.G(string s)'. // G(y); // warning Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("s", "void C.G(string s)").WithLocation(14, 15)); } [Fact] public void AssignmentInCondition_01() { var source = @"class C { object P => null; static void F(object o) { C? c; while ((c = o as C) != null) { o = c.P; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,17): warning CS8603: Possible null reference return. // object P => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(3, 17)); } [Fact] public void AssignmentInCondition_02() { var source = @"class C { object? P => null; static void F(object? o) { C? c; while ((c = o as C) != null) { o = c.P; } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void StructAsNullableInterface() { var source = @"interface I { void F(); } struct S : I { void I.F() { } } class C { static void F(I? i) { i.F(); } static void Main() { F(new S()); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // i.F(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "i").WithLocation(15, 9)); } [Fact] public void IsNull() { var source = @"class C { static void F1(object o) { } static void F2(object o) { } static void G(object? o) { if (o is null) { F1(o); } else { F2(o); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,16): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F1(object o)'. // F1(o); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("o", "void C.F1(object o)").WithLocation(9, 16)); } [Fact] public void IsInvalidConstant() { var source = @"class C { static void F(object o) { } static void G(object? o) { if (o is F) { F(o); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): error CS0428: Cannot convert method group 'F' to non-delegate type 'object'. Did you intend to invoke the method? // if (o is F) Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "F").WithArguments("F", "object").WithLocation(6, 18), // (8,15): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F(o); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("o", "void C.F(object o)").WithLocation(8, 15)); } [Fact] public void Feature() { var source = @"class C { static object F() => null; static object F(object? o) => o; }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8.WithFeature("staticNullChecking")); comp.VerifyDiagnostics( // (3,26): warning CS8603: Possible null reference return. // static object F() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(3, 26), // (4,35): warning CS8603: Possible null reference return. // static object F(object? o) => o; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(4, 35)); comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8.WithFeature("staticNullChecking", "0")); comp.VerifyDiagnostics( // (3,26): warning CS8603: Possible null reference return. // static object F() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(3, 26), // (4,35): warning CS8603: Possible null reference return. // static object F(object? o) => o; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(4, 35)); comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8.WithFeature("staticNullChecking", "1")); comp.VerifyDiagnostics( // (3,26): warning CS8603: Possible null reference return. // static object F() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(3, 26), // (4,35): warning CS8603: Possible null reference return. // static object F(object? o) => o; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(4, 35)); } [Fact] public void AllowMemberOptOut() { var source1 = @"partial class C { #nullable disable static void F(object o) { } }"; var source2 = @"partial class C { static void G(object o) { } static void M(object? o) { F(o); G(o); } }"; var comp = CreateCompilation( new[] { source1, source2 }, parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void M(object? o) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 25) ); comp = CreateCompilation( new[] { source1, source2 }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.G(object o)'. // G(o); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("o", "void C.G(object o)").WithLocation(9, 11)); } [Fact] public void InferLocalNullability() { var source = @"class C { static string? F(string s) => s; static void G(string s) { string x; x = F(s); F(x); string? y = s; y = F(y); F(y); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = F(s); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "F(s)").WithLocation(7, 13), // (8,11): warning CS8604: Possible null reference argument for parameter 's' in 'string? C.F(string s)'. // F(x); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("s", "string? C.F(string s)").WithLocation(8, 11), // (11,11): warning CS8604: Possible null reference argument for parameter 's' in 'string? C.F(string s)'. // F(y); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("s", "string? C.F(string s)").WithLocation(11, 11)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var declarator = tree.GetRoot().DescendantNodes().OfType().First(); var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator); Assert.Equal("System.String!", symbol.TypeWithAnnotations.ToTestDisplayString(true)); } [Fact] public void InferLocalType_UsedInDeclaration() { var source = @"using System; using System.Collections.Generic; class C { static T F(IEnumerable e) { throw new NotImplementedException(); } static void G() { var a = new[] { F(a) }; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,27): error CS0841: Cannot use local variable 'a' before it is declared // var a = new[] { F(a) }; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "a").WithArguments("a").WithLocation(11, 27), // (11,27): error CS0165: Use of unassigned local variable 'a' // var a = new[] { F(a) }; Diagnostic(ErrorCode.ERR_UseDefViolation, "a").WithArguments("a").WithLocation(11, 27)); } [Fact] public void InferLocalType_UsedInDeclaration_Script() { var source = @"using System; using System.Collections.Generic; static T F(IEnumerable e) { throw new NotImplementedException(); } var a = new[] { F(a) };"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Script.WithLanguageVersion(LanguageVersion.CSharp8)); comp.VerifyDiagnostics( // (7,5): error CS7019: Type of 'a' cannot be inferred since its initializer directly or indirectly refers to the definition. // var a = new[] { F(a) }; Diagnostic(ErrorCode.ERR_RecursivelyTypedVariable, "a").WithArguments("a").WithLocation(7, 5)); } [Fact] public void InferLocalType_UsedBeforeDeclaration() { var source = @"using System; using System.Collections.Generic; class C { static T F(IEnumerable e) { throw new NotImplementedException(); } static void G() { var a = new[] { F(b) }; var b = a; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,27): error CS0841: Cannot use local variable 'b' before it is declared // var a = new[] { F(b) }; Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "b").WithArguments("b").WithLocation(11, 27)); } [Fact] public void InferLocalType_OutVarError() { var source = @"using System; using System.Collections.Generic; class C { static T F(IEnumerable e) { throw new NotImplementedException(); } static void G() { dynamic d = null!; d.F(out var v); F(v).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,21): error CS8197: Cannot infer the type of implicitly-typed out variable 'v'. // d.F(out var v); Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedOutVariable, "v").WithArguments("v").WithLocation(12, 21)); } [Fact] public void InferLocalType_OutVarError_Script() { var source = @"using System; using System.Collections.Generic; static T F(IEnumerable e) { throw new NotImplementedException(); } dynamic d = null!; d.F(out var v); F(v).ToString();"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, parseOptions: TestOptions.Script.WithLanguageVersion(LanguageVersion.CSharp8)); comp.VerifyDiagnostics( // (8,13): error CS8197: Cannot infer the type of implicitly-typed out variable 'v'. // d.F(out var v); Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedOutVariable, "v").WithArguments("v").WithLocation(8, 13) ); } /// /// Default value for non-nullable parameter /// should not result in a warning at the call site. /// [WorkItem(26626, "https://github.com/dotnet/roslyn/issues/26626")] [Fact] public void ParameterDefaultValue_FromMetadata() { var source0 = @"public class C { public static void F(object o = null) { } }"; var comp0 = CreateCompilation( new[] { source0 }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp0.VerifyDiagnostics( // (3,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // public static void F(object o = null) Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(3, 37)); var ref0 = comp0.EmitToImageReference(); var source1 = @"class Program { static void Main() { C.F(); C.F(null); } }"; var comp1 = CreateCompilation( new[] { source1 }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8, references: new[] { ref0 }); comp1.VerifyDiagnostics( // (6,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // C.F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 13)); } [Fact] public void ParameterDefaultValue_WithSuppression() { var source0 = @"class C { void F(object o = null!) { } }"; var comp = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [WorkItem(26626, "https://github.com/dotnet/roslyn/issues/26626")] [Fact] public void ParameterDefaultValue_01() { var source = @"class C { const string? S0 = null; const string? S1 = """"; static string? F() => string.Empty; static void F0(string s = null) { } static void F1(string s = default) { } static void F2(string s = default(string)) { } static void F3(string x = (string)null, string y = (string?)null) { } static void F4(string s = S0) { } static void F5(string s = S1) { } static void F6(string s = F()) { } static void M() { F0(); F1(); F2(); F3(); F4(); F5(); F6(); F0(null); F0(string.Empty); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F0(string s = null) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 31), // (7,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F1(string s = default) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(7, 31), // (8,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F2(string s = default(string)) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default(string)").WithLocation(8, 31), // (9,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F3(string x = (string)null, string y = (string?)null) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string)null").WithLocation(9, 31), // (9,56): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F3(string x = (string)null, string y = (string?)null) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "(string?)null").WithLocation(9, 56), // (10,31): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F4(string s = S0) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "S0").WithLocation(10, 31), // (12,31): error CS1736: Default parameter value for 's' must be a compile-time constant // static void F6(string s = F()) { } Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "F()").WithArguments("s").WithLocation(12, 31), // (22,12): warning CS8625: Cannot convert null literal to non-nullable reference type. // F0(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(22, 12)); } [WorkItem(26626, "https://github.com/dotnet/roslyn/issues/26626")] [Fact] public void ParameterDefaultValue_02() { var source = @"class C { const string? S0 = null; static void F0(string s = null!) { } static void F1(string x = (string)null!, string y = ((string)null)!) { } static void F2(string x = default!, string y = default(string)!) { } static void F3(string s = (S0!)!) { } static void M() { F0(); F1(); F2(); F3(); F1(x: null); F1(y: null); F2(null!, null); } }"; // we should warn on the conversion of `null` to `string` in `(string)null` // Tracked by https://github.com/dotnet/roslyn/issues/32844 var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F1(x: null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 15), // (15,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F1(y: null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 15), // (16,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // F2(null!, null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 19) ); } [WorkItem(26626, "https://github.com/dotnet/roslyn/issues/26626")] [WorkItem(29910, "https://github.com/dotnet/roslyn/issues/29910")] [Fact] public void ParameterDefaultValue_03() { var source = @"interface I { } class C : I { } class P { static void F0(T t = default) { } static void F1(T t = null) where T : class { } static void F2(T t = default) where T : struct { } static void F3(T t = default) where T : new() { } static void F4(T t = null) where T : C { } static void F5(T t = default) where T : I { } static void F6(T t = default) where T : U { } static void G0() { F0(); F0(default); F0(new object()); F1(); F1(default); F1(new object()); F2(); F2(default); F2(2); F3(); F3(default); F3(new object()); F4(); F4(default); F4(new C()); F5(); F5(default); F5(new C()); F6(); F6(default); F6(new object()); } static void G0() { F0(); // 0 F0(default); // 0 F6(); // 0 F6(default); // 0 } static void G1() where T : class { F0(); // 1 F0(default); // 1 F1(); // 1 F1(default); // 1 F6(); // 1 F6(default); // 1 } static void G2() where T : struct { F0(); // 2 F0(default); // 2 F2(); // 2 F2(default); // 2 F3(); // 2 F3(default); // 2 F6(); // 2 F6(default); // 2 } static void G3() where T : new() { F0(); // 3 F0(default); // 3 F0(new T()); // 3 F3(); // 3 F3(default); // 3 F3(new T()); // 3 F6(); // 3 F6(default); // 3 F6(new T()); // 3 } static void G4() where T : C { F0(); // 4 F0(default); // 4 F1(); // 4 F1(default); // 4 F4(); // 4 F4(default); // 4 F5(); // 4 F5(default); // 4 F6(); // 4 F6(default); // 4 } static void G5() where T : I { F0(); // 5 F0(default); // 5 F5(); // 5 F5(default); // 5 F6(); // 5 F6(default); // 5 } static void G6() where T : U { F0(); // 6 F0(default); // 6 F6(); // 6 F6(default); // 6 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F1(T t = null) where T : class { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 29), // (9,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // static void F4(T t = null) where T : C { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(9, 29), // (15,20): warning CS8625: Cannot convert null literal to non-nullable reference type. // F0(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(15, 20), // (18,20): warning CS8625: Cannot convert null literal to non-nullable reference type. // F1(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(18, 20), // (24,20): warning CS8625: Cannot convert null literal to non-nullable reference type. // F3(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(24, 20), // (27,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F4(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(27, 15), // (30,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F5(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(30, 15), // (33,28): warning CS8625: Cannot convert null literal to non-nullable reference type. // F6(default); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(33, 28), // (39,15): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 0 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(39, 15), // (41,18): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 0 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(41, 18), // (46,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F0(default); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(46, 15), // (48,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F1(default); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(48, 15), // (50,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // F6(default); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(50, 18), // (66,15): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 3 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(66, 15), // (69,15): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F3(default); // 3 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(69, 15), // (72,18): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 3 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(72, 18), // (78,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F0(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(78, 15), // (80,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F1(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(80, 15), // (82,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F4(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(82, 15), // (84,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // F5(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(84, 15), // (86,18): warning CS8625: Cannot convert null literal to non-nullable reference type. // F6(default); // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(86, 18), // (91,15): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 5 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(91, 15), // (93,15): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F5(default); // 5 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(93, 15), // (95,18): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 5 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(95, 18), // (100,15): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F0(default); // 6 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(100, 15), // (102,18): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // F6(default); // 6 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(102, 18) ); // No warnings with C#7.3. comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); comp.VerifyDiagnostics( // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.3", "preview").WithLocation(1, 1) ); } [Fact] public void NonNullTypesInCSharp7_InSource() { var source = @" #nullable enable public class C { public static string field; } public class D { #nullable enable public static string field; #nullable enable public static string Method(string s) => throw null; #nullable enable public static string Property { get; set; } #nullable enable public static event System.Action Event; #nullable disable void M() { C.field = null; D.field = null; D.Method(null); D.Property = null; D.Event(); } } "; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7, skipUsesIsNullable: true); comp.VerifyDiagnostics( // (2,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(2, 2), // (9,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(9, 2), // (12,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(12, 2), // (15,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(15, 2), // (18,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(18, 2), // (20,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable disable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(20, 2) ); } [Fact] public void NonNullTypesInCSharp7_FromMetadata() { var libSource = @" #nullable enable public class C { public static string field; } public class D { #nullable enable public static string field; #nullable enable public static string Method(string s) => throw null!; #nullable enable public static string Property { get; set; } #nullable enable public static event System.Action Event; } "; var libComp = CreateCompilation(new[] { libSource }); libComp.VerifyDiagnostics( // (19,39): warning CS0067: The event 'D.Event' is never used // public static event System.Action Event; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("D.Event").WithLocation(19, 39) ); var source = @" class Client { void M() { C.field = null; D.field = null; D.Method(null); D.Property = null; D.Event(); } } "; var comp = CreateCompilation(source, references: new[] { libComp.EmitToImageReference() }, parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics( // (10,11): error CS0079: The event 'D.Event' can only appear on the left hand side of += or -= // D.Event(); Diagnostic(ErrorCode.ERR_BadEventUsageNoField, "Event").WithArguments("D.Event").WithLocation(10, 11) ); var comp2 = CreateCompilation(source, references: new[] { libComp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (10,11): error CS0079: The event 'D.Event' can only appear on the left hand side of += or -= // D.Event(); Diagnostic(ErrorCode.ERR_BadEventUsageNoField, "Event").WithArguments("D.Event").WithLocation(10, 11) ); } [WorkItem(26626, "https://github.com/dotnet/roslyn/issues/26626")] [Fact] public void ParameterDefaultValue_04() { var source = @"partial class C { static partial void F(object? x = null, object y = null); static partial void F(object? x, object y) { } static partial void G(object x, object? y); static partial void G(object x = null, object? y = null) { } static void M() { F(); G(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,34): warning CS1066: The default value specified for parameter 'x' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // static partial void G(object x = null, object? y = null) { } Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "x").WithArguments("x").WithLocation(6, 34), // (6,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // static partial void G(object x = null, object? y = null) { } Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 38), // (6,52): warning CS1066: The default value specified for parameter 'y' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // static partial void G(object x = null, object? y = null) { } Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "y").WithArguments("y").WithLocation(6, 52), // (3,56): warning CS8625: Cannot convert null literal to non-nullable reference type. // static partial void F(object? x = null, object y = null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(3, 56), // (10,9): error CS7036: There is no argument given that corresponds to the required formal parameter 'x' of 'C.G(object, object)' // G(); Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "G").WithArguments("x", "C.G(object, object?)").WithLocation(10, 9)); } [Fact] public void InvalidThrowTerm() { var source = @"class C { static string F(string s) => s + throw new System.Exception(); }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (3,38): error CS1525: Invalid expression term 'throw' // static string F(string s) => s + throw new System.Exception(); Diagnostic(ErrorCode.ERR_InvalidExprTerm, "throw new System.Exception()").WithArguments("throw").WithLocation(3, 38)); } [Fact] public void UnboxingConversion_01() { var source = @"using System.Collections.Generic; class Program { static IEnumerator M() => default(T); }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (4,37): error CS0266: Cannot implicitly convert type 'T' to 'System.Collections.Generic.IEnumerator'. An explicit conversion exists (are you missing a cast?) // static IEnumerator M() => default(T); Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "default(T)").WithArguments("T", "System.Collections.Generic.IEnumerator").WithLocation(4, 37), // (4,37): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // static IEnumerator M() => default(T); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(4, 37), // (4,37): warning CS8603: Possible null reference return. // static IEnumerator M() => default(T); Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T)").WithLocation(4, 37) ); } [Fact] [WorkItem(33359, "https://github.com/dotnet/roslyn/issues/33359")] public void UnboxingConversion_02() { var source = @"class C { interface I { } struct S : I { } static void Main() { M(null); } static void M(V v) where T : struct, V { var t = ((T) v); // 1 } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics( // (13,18): warning CS8605: Unboxing a possibly null value. // var t = ((T) v); // 1 Diagnostic(ErrorCode.WRN_UnboxPossibleNull, "(T) v").WithLocation(13, 18)); } [Fact] public void DeconstructionConversion_NoDeconstructMethod() { var source = @"class C { static void F(C c) { var (x, y) = c; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (5,22): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // var (x, y) = c; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "c").WithArguments("C", "Deconstruct").WithLocation(5, 22), // (5,22): error CS8129: No suitable Deconstruct instance or extension method was found for type 'C', with 2 out parameters and a void return type. // var (x, y) = c; Diagnostic(ErrorCode.ERR_MissingDeconstruct, "c").WithArguments("C", "2").WithLocation(5, 22), // (5,14): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'. // var (x, y) = c; Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(5, 14), // (5,17): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'. // var (x, y) = c; Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(5, 17)); } [Fact] [WorkItem(29916, "https://github.com/dotnet/roslyn/issues/29916")] public void ConditionalAccessDelegateInvoke() { var source = @"using System; class C { static T F(Func? f) { return f?.Invoke(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,17): error CS0023: Operator '?' cannot be applied to operand of type 'T' // return f?.Invoke(); Diagnostic(ErrorCode.ERR_BadUnaryOp, "?").WithArguments("?", "T").WithLocation(6, 17) ); } [Fact] public void NonNullTypes_DecodeAttributeCycle_01() { var source = @"using System.Runtime.InteropServices; interface I { int P { get; } } [StructLayout(LayoutKind.Auto)] struct S : I { int I.P => 0; }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void NonNullTypes_DecodeAttributeCycle_01_WithEvent() { var source = @"using System; using System.Runtime.InteropServices; interface I { event Func E; } [StructLayout(LayoutKind.Auto)] struct S : I { event Func I.E { add => throw null!; remove => throw null!; } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void NonNullTypes_DecodeAttributeCycle_02() { var source = @"[A(P)] class A : System.Attribute { string P => null; }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (1,4): error CS0120: An object reference is required for the non-static field, method, or property 'A.P' // [A(P)] Diagnostic(ErrorCode.ERR_ObjectRequired, "P").WithArguments("A.P").WithLocation(1, 4), // (1,2): error CS1729: 'A' does not contain a constructor that takes 1 arguments // [A(P)] Diagnostic(ErrorCode.ERR_BadCtorArgCount, "A(P)").WithArguments("A", "1").WithLocation(1, 2), // (4,17): warning CS8603: Possible null reference return. // string P => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(4, 17)); } [Fact] [WorkItem(29954, "https://github.com/dotnet/roslyn/issues/29954")] public void UnassignedOutParameterClass() { var source = @"class C { static void G(out C? c) { c.ToString(); // 1 c = null; c.ToString(); // 2 c = new C(); c.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS0269: Use of unassigned out parameter 'c' // c.ToString(); // 1 Diagnostic(ErrorCode.ERR_UseDefViolationOut, "c").WithArguments("c").WithLocation(5, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(7, 9)); } [Fact] public void UnassignedOutParameterClassField() { var source = @"class C { #pragma warning disable 0649 object? F; static void G(out C c) { object o = c.F; c.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,20): error CS0269: Use of unassigned out parameter 'c' // object o = c.F; Diagnostic(ErrorCode.ERR_UseDefViolationOut, "c").WithArguments("c").WithLocation(7, 20), // (5,17): error CS0177: The out parameter 'c' must be assigned to before control leaves the current method // static void G(out C c) Diagnostic(ErrorCode.ERR_ParamUnassigned, "G").WithArguments("c").WithLocation(5, 17), // (7,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object o = c.F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.F").WithLocation(7, 20), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F").WithLocation(8, 9)); } [Fact] public void UnassignedOutParameterStructField() { var source = @"struct S { #pragma warning disable 0649 object? F; static void G(out S s) { object o = s.F; s.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,20): error CS0170: Use of possibly unassigned field 'F' // object o = s.F; Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.F").WithArguments("F").WithLocation(7, 20), // (5,17): error CS0177: The out parameter 's' must be assigned to before control leaves the current method // static void G(out S s) Diagnostic(ErrorCode.ERR_ParamUnassigned, "G").WithArguments("s").WithLocation(5, 17), // (7,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object o = s.F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.F").WithLocation(7, 20), // (8,9): warning CS8602: Dereference of a possibly null reference. // s.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.F").WithLocation(8, 9) ); } [Fact] public void UnassignedLocalField() { var source = @"class C { static void F() { S s; C c; c = s.F; s.F.ToString(); } } struct S { internal C? F; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): error CS0170: Use of possibly unassigned field 'F' // c = s.F; Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.F").WithArguments("F").WithLocation(7, 13), // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = s.F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.F").WithLocation(7, 13), // (8,9): warning CS8602: Dereference of a possibly null reference. // s.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.F").WithLocation(8, 9), // (13,17): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value null // internal C? F; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "null").WithLocation(13, 17) ); } [Fact] public void UnassignedLocalField_Conditional() { var source = @"class C { static void F(bool b) { S s; object o; if (b) { s.F = new object(); s.G = new object(); } else { o = s.F; } o = s.G; } } struct S { internal object? F; internal object? G; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): error CS0170: Use of possibly unassigned field 'F' // o = s.F; Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.F").WithArguments("F").WithLocation(14, 17), // (14,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = s.F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.F").WithLocation(14, 17), // (16,13): error CS0170: Use of possibly unassigned field 'G' // o = s.G; Diagnostic(ErrorCode.ERR_UseDefViolationField, "s.G").WithArguments("G").WithLocation(16, 13), // (16,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = s.G; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.G").WithLocation(16, 13) ); } [Fact] public void UnassignedLocalProperty() { var source = @"class C { static void F() { S s; C c; c = s.P; s.P.ToString(); } } struct S { internal C? P { get => null; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = s.P; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s.P").WithLocation(7, 13), // (8,9): warning CS8602: Dereference of a possibly null reference. // s.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.P").WithLocation(8, 9)); } [Fact] public void UnassignedClassAutoProperty() { var source = @"class C { object? P { get; } void M(out object o) { o = P; P.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8601: Possible null reference assignment. // o = P; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "P").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "P").WithLocation(7, 9)); } [Fact] public void UnassignedClassAutoProperty_Constructor() { var source = @"class C { object? P { get; } C(out object o) { o = P; P.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8601: Possible null reference assignment. // o = P; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "P").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "P").WithLocation(7, 9)); } [Fact] public void UnassignedStructAutoProperty() { var source = @"struct S { object? P { get; } void M(out object o) { o = P; P.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8601: Possible null reference assignment. // o = P; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "P").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "P").WithLocation(7, 9)); } [Fact] public void UnassignedStructAutoProperty_Constructor() { var source = @"struct S { object? P { get; } S(out object o) { o = P; P.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): error CS8079: Use of possibly unassigned auto-implemented property 'P' // o = P; Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "P").WithArguments("P").WithLocation(6, 13), // (4,5): error CS0843: Auto-implemented property 'S.P' must be fully assigned before control is returned to the caller. // S(out object o) Diagnostic(ErrorCode.ERR_UnassignedThisAutoProperty, "S").WithArguments("S.P").WithLocation(4, 5), // (6,13): warning CS8601: Possible null reference assignment. // o = P; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "P").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "P").WithLocation(7, 9) ); } [Fact] public void ParameterField_Class() { var source = @"class C { #pragma warning disable 0649 object? F; static void M(C x) { C y = x; object z = y.F; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object z = y.F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y.F").WithLocation(8, 20)); } [Fact] public void ParameterField_Struct() { var source = @"struct S { #pragma warning disable 0649 object? F; static void M(S x) { S y = x; object z = y.F; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object z = y.F; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y.F").WithLocation(8, 20)); } [Fact] public void InstanceFieldStructTypeExpressionReceiver() { var source = @"struct S { #pragma warning disable 0649 object? F; void M() { S.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): error CS0120: An object reference is required for the non-static field, method, or property 'S.F' // S.F.ToString(); Diagnostic(ErrorCode.ERR_ObjectRequired, "S.F").WithArguments("S.F").WithLocation(7, 9)); } [Fact] public void InstanceFieldPrimitiveRecursiveStruct() { var source = @"#pragma warning disable 0649 namespace System { public class Object { public int GetHashCode() => 0; } public abstract class ValueType { } public struct Void { } public struct Int32 { Int32 _value; object? _f; void M() { _value = _f.GetHashCode(); } } public class String { } public struct Boolean { } public struct Enum { } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } }"; var comp = CreateEmptyCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,22): warning CS8602: Dereference of a possibly null reference. // _value = _f.GetHashCode(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "_f").WithLocation(16, 22) ); } [Fact] public void Pointer() { var source = @"class C { static unsafe void F(int* p) { *p = 0; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(TestOptions.UnsafeReleaseDll)); comp.VerifyDiagnostics(); } [Fact] public void TaskMethodReturningNull() { var source = @"using System.Threading.Tasks; class C { static Task F0() => null; static Task F1() => null; static Task F2() { return null; } static Task F3() { return default; } static Task F4() { return default(Task); } static Task F5() where T : class { return null; } static Task F6() where T : class => null; static Task? G0() => null; static Task? G1() => null; static Task? G3() { return default; } static Task? G6() where T : class => null; }"; var comp = CreateCompilationWithMscorlib46(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,25): warning CS8603: Possible null reference return. // static Task F0() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(4, 25), // (5,33): warning CS8603: Possible null reference return. // static Task F1() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(5, 33), // (6,40): warning CS8603: Possible null reference return. // static Task F2() { return null; } Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 40), // (7,37): warning CS8603: Possible null reference return. // static Task F3() { return default; } Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(7, 37), // (8,37): warning CS8603: Possible null reference return. // static Task F4() { return default(Task); } Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(Task)").WithLocation(8, 37), // (9,53): warning CS8603: Possible null reference return. // static Task F5() where T : class { return null; } Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(9, 53), // (10,48): warning CS8603: Possible null reference return. // static Task F6() where T : class => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(10, 48)); } // https://github.com/dotnet/roslyn/issues/29957: Should not report WRN_NullReferenceReturn for F0. [WorkItem(23275, "https://github.com/dotnet/roslyn/issues/23275")] [WorkItem(29957, "https://github.com/dotnet/roslyn/issues/29957")] [Fact] public void AsyncTaskMethodReturningNull() { var source = @"#pragma warning disable 1998 using System.Threading.Tasks; class C { static async Task F0() { return null; } static async Task F1() => null; static async Task F2() { return null; } static async Task F3() { return default; } static async Task F4() { return default(T); } static async Task F5() where T : class { return null; } static async Task F6() where T : class => null; static async Task? G0() { return null; } static async Task? G1() => null; static async Task? G3() { return default; } static async Task? G6() where T : class => null; }"; var comp = CreateCompilationWithMscorlib46(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,30): error CS1997: Since 'C.F0()' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'? // static async Task F0() { return null; } Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("C.F0()").WithLocation(5, 30), // (6,39): warning CS8603: Possible null reference return. // static async Task F1() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(6, 39), // (8,43): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static async Task F3() { return default; } Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(8, 43), // (9,43): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static async Task F4() { return default(T); } Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(9, 43), // (10,59): warning CS8603: Possible null reference return. // static async Task F5() where T : class { return null; } Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(10, 59), // (12,31): error CS1997: Since 'C.G0()' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'? // static async Task? G0() { return null; } Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("C.G0()").WithLocation(12, 31), // (13,40): warning CS8603: Possible null reference return. // static async Task? G1() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(13, 40), // (14,44): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // static async Task? G3() { return default; } Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(14, 44) ); } [Fact] public void IncrementWithErrors() { var source = @"using System.Threading.Tasks; class C { static async Task F(ref int i) { return await Task.Run(() => i++); } }"; var comp = CreateCompilationWithMscorlib46(source); comp.VerifyDiagnostics( // (4,38): error CS1988: Async methods cannot have ref or out parameters // static async Task F(ref int i) Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i").WithLocation(4, 38), // (6,37): error CS1628: Cannot use ref or out parameter 'i' inside an anonymous method, lambda expression, or query expression // return await Task.Run(() => i++); Diagnostic(ErrorCode.ERR_AnonDelegateCantUse, "i").WithArguments("i").WithLocation(6, 37)); } [Fact] public void NullCastToValueType() { var source = @"struct S { } class C { static void M() { S s = (S)null; s.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): error CS0037: Cannot convert null to 'S' because it is a non-nullable value type // S s = (S)null; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "(S)null").WithArguments("S").WithLocation(6, 15)); } [Fact] public void NullCastToUnannotatableReferenceTypedTypeParameter() { var source = @"struct S { } class C { static T M1() where T: class? { return (T)null; // 1 } static T M2() where T: C? { return (T)null; // 2 } static T M3() where T: class? { return null; // 3 } static T M4() where T: C? { return null; // 4 } static T M5() where T: class? { return (T)null!; } static T M6() where T: C? { return (T)null!; } static T M7() where T: class? { return null!; } static T M8() where T: C? { return null!; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // return (T)null; // 1 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "(T)null").WithArguments("T").WithLocation(6, 16), // (10,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // return (T)null; // 2 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "(T)null").WithArguments("T").WithLocation(10, 16), // (14,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // return null; // 3 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(14, 16), // (18,16): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // return null; // 4 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(18, 16)); } [Fact] public void LiftedUserDefinedConversion() { var source = @"#pragma warning disable 0649 struct A { public static implicit operator B(A a) => new B(); } struct B { internal T F; } class C { static void F(A? x, A? y) { B? z = x; z?.F.ToString(); B? w = y; w?.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,11): warning CS8602: Dereference of a possibly null reference. // w?.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".F").WithLocation(17, 11)); } [Fact] public void LiftedBinaryOperator() { var source = @"struct A { public static A operator +(A a1, A a2) => throw null!; } class C2 { static void F(A? x, A? y) { var sum1 = (x + y)/*T:A?*/; sum1.ToString(); if (x == null || y == null) return; var sum2 = (x + y)/*T:A?*/; sum2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void GroupBy() { var source = @"using System.Linq; class Program { static void Main() { var items = from i in Enumerable.Range(0, 3) group (long)i by i; } }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } // Tests for NullableWalker.HasImplicitTypeArguments. [Fact] public void ExplicitTypeArguments() { var source = @"interface I { } class C { C P => throw new System.Exception(); I F(T t) { throw new System.Exception(); } static void M(C c) { c.P.F(string.Empty); (new[]{ c })[0].F(string.Empty); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void MultipleConversions_01() { var source = @"class A { public static implicit operator C(A a) => new C(); } class B : A { } class C { static void F(B? x, B y) { C c; c = x; // (ImplicitUserDefined)(ImplicitReference) c = y; // (ImplicitUserDefined)(ImplicitReference) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8604: Possible null reference argument for parameter 'a' in 'A.implicit operator C(A a)'. // c = x; // (ImplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("a", "A.implicit operator C(A a)").WithLocation(13, 13)); } [Fact] public void MultipleConversions_02() { var source = @"class A { } class B : A { } class C { public static implicit operator B?(C c) => null; static void F(C c) { A a = c; // (ImplicitReference)(ImplicitUserDefined) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // A a = c; // (ImplicitReference)(ImplicitUserDefined) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c").WithLocation(12, 15)); } [Fact] public void MultipleConversions_03() { var source = @"struct S { public static implicit operator S(T t) => default; static void M() { S s = true; // (ImplicitUserDefined)(Boxing) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void MultipleConversions_04() { var source = @"struct S { public static implicit operator T(S s) => throw new System.Exception(); static void M() { bool b = new S(); // (Unboxing)(ExplicitUserDefined) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): error CS0266: Cannot implicitly convert type 'S' to 'bool'. An explicit conversion exists (are you missing a cast?) // bool b = new S(); // (Unboxing)(ExplicitUserDefined) Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "new S()").WithArguments("S", "bool").WithLocation(6, 18)); } [Fact] public void MultipleConversions_Explicit_01() { var source = @"class A { public static explicit operator C(A a) => new C(); } class B : A { } class C { static void F1(B b1) { C? c; c = (C)b1; // (ExplicitUserDefined)(ImplicitReference) c = (C?)b1; // (ExplicitUserDefined)(ImplicitReference) } static void F2(B? b2) { C? c; c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,16): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator C(A a)'. // c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2").WithArguments("a", "A.explicit operator C(A a)").WithLocation(19, 16), // (20,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator C(A a)'. // c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2").WithArguments("a", "A.explicit operator C(A a)").WithLocation(20, 17)); } [Fact] public void MultipleConversions_Explicit_02() { var source = @"class A { public static explicit operator C?(A? a) => new D(); } class B : A { } class C { } class D : C { } class P { static void F1(A a1, B b1) { C? c; c = (C)a1; // (ExplicitUserDefined) c = (C?)a1; // (ExplicitUserDefined) c = (C)b1; // (ExplicitUserDefined)(ImplicitReference) c = (C?)b1; // (ExplicitUserDefined)(ImplicitReference) c = (C)(B)a1; c = (C)(B?)a1; c = (C?)(B)a1; c = (C?)(B?)a1; D? d; d = (D)a1; // (ExplicitReference)(ExplicitUserDefined) d = (D?)a1; // (ExplicitReference)(ExplicitUserDefined) d = (D)b1; // (ExplicitReference)(ExplicitUserDefined)(ImplicitReference) d = (D?)b1; // (ExplicitReference)(ExplicitUserDefined)(ImplicitReference) } static void F2(A? a2, B? b2) { C? c; c = (C)a2; // (ExplicitUserDefined) c = (C?)a2; // (ExplicitUserDefined) c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) D? d; d = (D)a2; // (ExplicitReference)(ExplicitUserDefined) d = (D?)a2; // (ExplicitReference)(ExplicitUserDefined) d = (D)b2; // (ExplicitReference)(ExplicitUserDefined)(ImplicitReference) d = (D?)b2; // (ExplicitReference)(ExplicitUserDefined)(ImplicitReference) d = (D)(A)b2; d = (D)(A?)b2; d = (D?)(A)b2; d = (D?)(A?)b2; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = (C)a1; // (ExplicitUserDefined) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)a1").WithLocation(13, 13), // (15,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = (C)b1; // (ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)b1").WithLocation(15, 13), // (17,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = (C)(B)a1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)(B)a1").WithLocation(17, 13), // (18,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = (C)(B?)a1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)(B?)a1").WithLocation(18, 13), // (22,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)a1; // (ExplicitReference)(ExplicitUserDefined) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(D)a1").WithLocation(22, 13), // (24,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)b1; // (ExplicitReference)(ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(D)b1").WithLocation(24, 13), // (30,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = (C)a2; // (ExplicitUserDefined) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)a2").WithLocation(30, 13), // (32,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)b2").WithLocation(32, 13), // (35,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)a2; // (ExplicitReference)(ExplicitUserDefined) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(D)a2").WithLocation(35, 13), // (37,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)b2; // (ExplicitReference)(ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(D)b2").WithLocation(37, 13), // (39,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)(A)b2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)b2").WithLocation(39, 16), // (39,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)(A)b2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(D)(A)b2").WithLocation(39, 13), // (40,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D)(A?)b2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(D)(A?)b2").WithLocation(40, 13), // (41,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // d = (D?)(A)b2; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)b2").WithLocation(41, 17)); } [Fact] public void MultipleConversions_Explicit_03() { var source = @"class A { public static explicit operator S(A a) => new S(); } class B : A { } struct S { } class C { static void F(B? b) { S? s; s = (S)b; // (ExplicitUserDefined)(ImplicitReference) s = (S?)b; // (ImplicitNullable)(ExplicitUserDefined)(ImplicitReference) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,16): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator S(A a)'. // s = (S)b; // (ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("a", "A.explicit operator S(A a)").WithLocation(12, 16), // (13,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator S(A a)'. // s = (S?)b; // (ImplicitNullable)(ExplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("a", "A.explicit operator S(A a)").WithLocation(13, 17)); } [Fact] [WorkItem(29960, "https://github.com/dotnet/roslyn/issues/29960")] public void MultipleConversions_Explicit_04() { var source = @"struct S { public static explicit operator A?(S s) => throw null!; } class A { internal void F() { } } class B : A { } class C { static void F(S s) { var b1 = (B)s; b1.F(); B b2 = (B)s; b2.F(); A a = (B)s; a.F(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29960: Should only report one WRN_ConvertingNullableToNonNullable // warning for `B b2 = (B)s;` and `A a = (B)s;`. comp.VerifyDiagnostics( // (16,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // var b1 = (B)s; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)s").WithLocation(16, 18), // (17,9): warning CS8602: Dereference of a possibly null reference. // b1.F(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b1").WithLocation(17, 9), // (18,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // B b2 = (B)s; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)s").WithLocation(18, 16), // (19,9): warning CS8602: Dereference of a possibly null reference. // b2.F(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b2").WithLocation(19, 9), // (20,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // A a = (B)s; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)s").WithLocation(20, 15), // (20,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // A a = (B)s; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)s").WithLocation(20, 15), // (21,9): warning CS8602: Dereference of a possibly null reference. // a.F(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(21, 9)); } [Fact] [WorkItem(29699, "https://github.com/dotnet/roslyn/issues/29699")] public void MultipleTupleConversions_01() { var source = @"class A { public static implicit operator C(A a) => new C(); } class B : A { } class C { static void F((B?, B) x, (B, B?) y, (B, B) z) { (C, C?) c; c = x; // (ImplicitTuple)(ImplicitUserDefined)(ImplicitReference) c = y; // (ImplicitTuple)(ImplicitUserDefined)(ImplicitReference) c = z; // (ImplicitTuple)(ImplicitUserDefined)(ImplicitReference) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8604: Possible null reference argument for parameter 'a' in 'A.implicit operator C(A a)'. // c = x; // (ImplicitTuple)(ImplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("a", "A.implicit operator C(A a)").WithLocation(13, 13), // (13,13): warning CS8619: Nullability of reference types in value of type '(B?, B)' doesn't match target type '(C, C?)'. // c = x; // (ImplicitTuple)(ImplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("(B?, B)", "(C, C?)").WithLocation(13, 13), // (14,13): warning CS8604: Possible null reference argument for parameter 'a' in 'A.implicit operator C(A a)'. // c = y; // (ImplicitTuple)(ImplicitUserDefined)(ImplicitReference) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("a", "A.implicit operator C(A a)").WithLocation(14, 13)); } [Fact] public void MultipleTupleConversions_02() { var source = @"class A { } class B : A { } class C { public static implicit operator B(C c) => new C(); static void F(C? x, C y) { (A, A?) t = (x, y); // (ImplicitTuple)(ImplicitReference)(ImplicitUserDefined) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,17): warning CS0219: The variable 't' is assigned but its value is never used // (A, A?) t = (x, y); // (ImplicitTuple)(ImplicitReference)(ImplicitUserDefined) Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t").WithArguments("t").WithLocation(12, 17), // (12,22): warning CS8604: Possible null reference argument for parameter 'c' in 'C.implicit operator B(C c)'. // (A, A?) t = (x, y); // (ImplicitTuple)(ImplicitReference)(ImplicitUserDefined) Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("c", "C.implicit operator B(C c)").WithLocation(12, 22)); } [Fact] [WorkItem(29966, "https://github.com/dotnet/roslyn/issues/29966")] public void Conversions_ImplicitTupleLiteral_01() { var source = @"#pragma warning disable 0219 interface I { } interface IIn { } interface IOut { } class A : I { } class B : IIn { } class C : IOut { } static class E { static void F1(string x, string? y) { (string, string) t1 = (x, y); // 1 (string?, string?) u1 = (x, y); (object, object) v1 = (x, y); // 2 (object?, object?) w1 = (x, y); F1A((x, y)); // 3 F1B((x, y)); F1C((x, y)); // 4 F1D((x, y)); } static void F1A((string, string) t) { } static void F1B((string?, string?) t) { } static void F1C((object, object) t) { } static void F1D((object?, object?) t) { } static void F2(A x, A y) { (A, A) t2 = (x, y); // 5 (A, A) u2 = (x, y); // 6 (I, I) v2 = (x, y); // 7 (I, I) w2 = (x, y); // 8 F2A((x, y)); // 9 F2B((x, y)); // 10 F2C((x, y)); // 11 F2D((x, y)); // 12 } static void F2A((A, A) t) { } static void F2B((A, A) t) { } static void F2C((I, I) t) { } static void F2D((I, I) t) { } static void F3(B x, B y) { (B, B) t3 = (x, y); // 13 (B, B) u3 = (x, y); // 14 (IIn, IIn) v3 = (x, y); (IIn, IIn) w3 = (x, y); // 15 F3A((x, y)); F3B((x, y)); // 16 } static void F3A((IIn, IIn) t) { } static void F3B((IIn, IIn) t) { } static void F4(C x, C y) { (C, C) t4 = (x, y); // 17 (C, C) u4 = (x, y); // 18 (IOut, IOut) v4 = (x, y); // 19 (IOut, IOut) w4 = (x, y); F4A((x, y)); // 20 F4B((x, y)); } static void F4A((IOut, IOut) t) { } static void F4B((IOut, IOut) t) { } static void F5(U u) where U : T { (T, T) t5 = (u, default(T)); (object, object) v5 = (default(T), u); // 21 (object?, object?) w5 = (default(T), u); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29966: Report WRN_NullabilityMismatchInArgument rather than ...Assignment. comp.VerifyDiagnostics( // (12,31): warning CS8619: Nullability of reference types in value of type '(string x, string? y)' doesn't match target type '(string, string)'. // (string, string) t1 = (x, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(string x, string? y)", "(string, string)").WithLocation(12, 31), // (14,31): warning CS8619: Nullability of reference types in value of type '(object x, object? y)' doesn't match target type '(object, object)'. // (object, object) v1 = (x, y); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(object x, object? y)", "(object, object)").WithLocation(14, 31), // (16,13): warning CS8620: Argument of type '(string x, string? y)' cannot be used as an input of type '(string, string)' for parameter 't' in 'void E.F1A((string, string) t)' due to differences in the nullability of reference types. // F1A((x, y)); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(x, y)").WithArguments("(string x, string? y)", "(string, string)", "t", "void E.F1A((string, string) t)").WithLocation(16, 13), // (18,13): warning CS8620: Argument of type '(object x, object? y)' cannot be used as an input of type '(object, object)' for parameter 't' in 'void E.F1C((object, object) t)' due to differences in the nullability of reference types. // F1C((x, y)); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(x, y)").WithArguments("(object x, object? y)", "(object, object)", "t", "void E.F1C((object, object) t)").WithLocation(18, 13), // (27,37): warning CS8619: Nullability of reference types in value of type '(A x, A y)' doesn't match target type '(A, A)'. // (A, A) t2 = (x, y); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(A x, A y)", "(A, A)").WithLocation(27, 37), // (28,39): warning CS8619: Nullability of reference types in value of type '(A x, A y)' doesn't match target type '(A, A)'. // (A, A) u2 = (x, y); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(A x, A y)", "(A, A)").WithLocation(28, 39), // (29,41): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // (I, I) v2 = (x, y); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "I").WithLocation(29, 41), // (30,40): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // (I, I) w2 = (x, y); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "I").WithLocation(30, 40), // (31,13): warning CS8620: Argument of type '(A x, A y)' cannot be used as an input of type '(A, A)' for parameter 't' in 'void E.F2A((A, A) t)' due to differences in the nullability of reference types. // F2A((x, y)); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(x, y)").WithArguments("(A x, A y)", "(A, A)", "t", "void E.F2A((A, A) t)").WithLocation(31, 13), // (32,13): warning CS8620: Argument of type '(A x, A y)' cannot be used as an input of type '(A, A)' for parameter 't' in 'void E.F2B((A, A) t)' due to differences in the nullability of reference types. // F2B((x, y)); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(x, y)").WithArguments("(A x, A y)", "(A, A)", "t", "void E.F2B((A, A) t)").WithLocation(32, 13), // (33,17): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // F2C((x, y)); // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "I").WithLocation(33, 17), // (34,14): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // F2D((x, y)); // 12 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "I").WithLocation(34, 14), // (42,37): warning CS8619: Nullability of reference types in value of type '(B x, B y)' doesn't match target type '(B, B)'. // (B, B) t3 = (x, y); // 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(B x, B y)", "(B, B)").WithLocation(42, 37), // (43,39): warning CS8619: Nullability of reference types in value of type '(B x, B y)' doesn't match target type '(B, B)'. // (B, B) u3 = (x, y); // 14 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(B x, B y)", "(B, B)").WithLocation(43, 39), // (45,44): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // (IIn, IIn) w3 = (x, y); // 15 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "IIn").WithLocation(45, 44), // (47,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // F3B((x, y)); // 16 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "IIn").WithLocation(47, 14), // (53,37): warning CS8619: Nullability of reference types in value of type '(C x, C y)' doesn't match target type '(C, C)'. // (C, C) t4 = (x, y); // 17 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(C x, C y)", "(C, C)").WithLocation(53, 37), // (54,39): warning CS8619: Nullability of reference types in value of type '(C x, C y)' doesn't match target type '(C, C)'. // (C, C) u4 = (x, y); // 18 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(C x, C y)", "(C, C)").WithLocation(54, 39), // (55,47): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // (IOut, IOut) v4 = (x, y); // 19 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "IOut").WithLocation(55, 47), // (57,17): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // F4A((x, y)); // 20 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "IOut").WithLocation(57, 17), // (64,26): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (T, T) t5 = (u, default(T)); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(64, 26), // (65,31): warning CS8619: Nullability of reference types in value of type '(object?, object? u)' doesn't match target type '(object, object)'. // (object, object) v5 = (default(T), u); // 21 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(T), u)").WithArguments("(object?, object? u)", "(object, object)").WithLocation(65, 31), // (65,32): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (object, object) v5 = (default(T), u); // 21 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(65, 32), // (66,34): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (object?, object?) w5 = (default(T), u); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(66, 34)); } [Fact] public void Conversions_ImplicitTupleLiteral_02() { var source = @"#pragma warning disable 0219 interface I { } interface IIn { } interface IOut { } class A : I { } class B : IIn { } class C : IOut { } static class E { static void F1(string x, string? y) { (string, string)? t1 = (x, y); // 1 (string?, string?)? u1 = (x, y); (object, object)? v1 = (x, y); // 2 (object?, object?)? w1 = (x, y); } static void F2(A x, A y) { (A, A)? t2 = (x, y); // 3 (A, A)? u2 = (x, y); // 4 (I, I)? v2 = (x, y); // 5 (I, I)? w2 = (x, y); // 6 } static void F3(B x, B y) { (IIn, IIn)? v3 = (x, y); (IIn, IIn)? w3 = (x, y); // 7 } static void F4(C x, C y) { (IOut, IOut)? v4 = (x, y); // 8 (IOut, IOut)? w4 = (x, y); } static void F5(U u) where U : T { (T, T)? t5 = (u, default(T)); // 9 (object, object)? v5 = (default(T), u); // 10 (object?, object?)? w5 = (default(T), u); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,32): warning CS8619: Nullability of reference types in value of type '(string x, string? y)' doesn't match target type '(string, string)?'. // (string, string)? t1 = (x, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(string x, string? y)", "(string, string)?").WithLocation(12, 32), // (14,32): warning CS8619: Nullability of reference types in value of type '(object x, object? y)' doesn't match target type '(object, object)?'. // (object, object)? v1 = (x, y); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(object x, object? y)", "(object, object)?").WithLocation(14, 32), // (19,38): warning CS8619: Nullability of reference types in value of type '(A x, A y)' doesn't match target type '(A, A)?'. // (A, A)? t2 = (x, y); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(A x, A y)", "(A, A)?").WithLocation(19, 38), // (20,40): warning CS8619: Nullability of reference types in value of type '(A x, A y)' doesn't match target type '(A, A)?'. // (A, A)? u2 = (x, y); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(A x, A y)", "(A, A)?").WithLocation(20, 40), // (21,42): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // (I, I)? v2 = (x, y); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "I").WithLocation(21, 42), // (22,41): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // (I, I)? w2 = (x, y); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "I").WithLocation(22, 41), // (27,45): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // (IIn, IIn)? w3 = (x, y); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "IIn").WithLocation(27, 45), // (31,48): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // (IOut, IOut)? v4 = (x, y); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "IOut").WithLocation(31, 48), // (36,27): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (T, T)? t5 = (u, default(T)); // 9 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(36, 27), // (37,32): warning CS8619: Nullability of reference types in value of type '(object?, object? u)' doesn't match target type '(object, object)?'. // (object, object)? v5 = (default(T), u); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(T), u)").WithArguments("(object?, object? u)", "(object, object)?").WithLocation(37, 32), // (37,33): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (object, object)? v5 = (default(T), u); // 10 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(37, 33), // (38,35): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (object?, object?)? w5 = (default(T), u); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(38, 35)); } [Fact] public void Conversions_ImplicitTuple() { var source = @"#pragma warning disable 0219 interface I { } interface IIn { } interface IOut { } class A : I { } class B : IIn { } class C : IOut { } class D { static void F1((string x, string?) a1) { (string, string) t1 = a1; // 1 (string?, string?) u1 = a1; (object, object) v1 = a1; // 2 (object?, object?) w1 = a1; } static void F2((A x, A) a2) { (A, A) t2 = a2; // 3 (A, A) u2 = a2; // 4 (I, I) v2 = a2; // 5 (I, I) w2 = a2; // 6 } static void F3((B x, B) a3) { (IIn, IIn) v3 = a3; (IIn, IIn) w3 = a3; // 7 } static void F4((C x, C) a4) { (IOut, IOut) v4 = a4; // 8 (IOut, IOut) w4 = a4; } static void F5((U, U) a5) where U : T { (U, T) t5 = a5; (object, object) v5 = a5; // 9 (object?, object?) w5 = a5; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,31): warning CS8619: Nullability of reference types in value of type '(string x, string?)' doesn't match target type '(string, string)'. // (string, string) t1 = a1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a1").WithArguments("(string x, string?)", "(string, string)").WithLocation(12, 31), // (14,31): warning CS8619: Nullability of reference types in value of type '(string x, string?)' doesn't match target type '(object, object)'. // (object, object) v1 = a1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a1").WithArguments("(string x, string?)", "(object, object)").WithLocation(14, 31), // (19,37): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(A, A)'. // (A, A) t2 = a2; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("(A x, A)", "(A, A)").WithLocation(19, 37), // (20,39): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(A, A)'. // (A, A) u2 = a2; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("(A x, A)", "(A, A)").WithLocation(20, 39), // (21,37): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(I, I)'. // (I, I) v2 = a2; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("(A x, A)", "(I, I)").WithLocation(21, 37), // (22,39): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(I, I)'. // (I, I) w2 = a2; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("(A x, A)", "(I, I)").WithLocation(22, 39), // (27,43): warning CS8619: Nullability of reference types in value of type '(B x, B)' doesn't match target type '(IIn, IIn)'. // (IIn, IIn) w3 = a3; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a3").WithArguments("(B x, B)", "(IIn, IIn)").WithLocation(27, 43), // (31,43): warning CS8619: Nullability of reference types in value of type '(C x, C)' doesn't match target type '(IOut, IOut)'. // (IOut, IOut) v4 = a4; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a4").WithArguments("(C x, C)", "(IOut, IOut)").WithLocation(31, 43), // (37,31): warning CS8619: Nullability of reference types in value of type '(U, U)' doesn't match target type '(object, object)'. // (object, object) v5 = a5; // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a5").WithArguments("(U, U)", "(object, object)").WithLocation(37, 31)); } [Fact] public void Conversions_ExplicitTupleLiteral_01() { var source = @"#pragma warning disable 0219 interface I { } interface IIn { } interface IOut { } sealed class A : I { } sealed class B : IIn { } sealed class C : IOut { } class D { static void F1(string x, string? y) { var t1 = ((string, string))(x, y); // 1 var u1 = ((string?, string?))(x, y); var v1 = ((object, object))(x, y); // 2 var w1 = ((object?, object?))(x, y); } static void F2(A x, A y) { var t2 = ((A, A))(x, y); // 3 var u2 = ((A, A))(x, y); // 4 var v2 = ((I, I))(x, y); // 5 var w2 = ((I, I))(x, y); // 6 } static void F3(B x, B y) { var v3 = ((IIn, IIn))(x, y); var w3 = ((IIn, IIn))(x, y); // 7 } static void F4(C x, C y) { var v4 = ((IOut, IOut))(x, y); // 8 var w4 = ((IOut, IOut))(x, y); } static void F5(T t) where U : T { var t5 = ((U, U))(t, default(T)); // 9 var v5 = ((object, object))(default(T), t); // 10 var w5 = ((object?, object?))(default(T), t); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,18): warning CS8619: Nullability of reference types in value of type '(string x, string? y)' doesn't match target type '(string, string)'. // var t1 = ((string, string))(x, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((string, string))(x, y)").WithArguments("(string x, string? y)", "(string, string)").WithLocation(12, 18), // (14,18): warning CS8619: Nullability of reference types in value of type '(object x, object? y)' doesn't match target type '(object, object)'. // var v1 = ((object, object))(x, y); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object))(x, y)").WithArguments("(object x, object? y)", "(object, object)").WithLocation(14, 18), // (14,40): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v1 = ((object, object))(x, y); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(14, 40), // (19,18): warning CS8619: Nullability of reference types in value of type '(A x, A y)' doesn't match target type '(A, A)'. // var t2 = ((A, A))(x, y); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((A, A))(x, y)").WithArguments("(A x, A y)", "(A, A)").WithLocation(19, 18), // (20,18): warning CS8619: Nullability of reference types in value of type '(A x, A y)' doesn't match target type '(A, A)'. // var u2 = ((A, A))(x, y); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((A, A))(x, y)").WithArguments("(A x, A y)", "(A, A)").WithLocation(20, 18), // (21,46): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // var v2 = ((I, I))(x, y); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "I").WithLocation(21, 46), // (22,45): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // var w2 = ((I, I))(x, y); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "I").WithLocation(22, 45), // (27,49): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // var w3 = ((IIn, IIn))(x, y); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "IIn").WithLocation(27, 49), // (31,52): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // var v4 = ((IOut, IOut))(x, y); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "IOut").WithLocation(31, 52), // (36,27): warning CS8601: Possible null reference assignment. // var t5 = ((U, U))(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t").WithLocation(36, 27), // (36,30): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var t5 = ((U, U))(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(36, 30), // (36,30): warning CS8601: Possible null reference assignment. // var t5 = ((U, U))(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "default(T)").WithLocation(36, 30), // (37,18): warning CS8619: Nullability of reference types in value of type '(object?, object? t)' doesn't match target type '(object, object)'. // var v5 = ((object, object))(default(T), t); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object))(default(T), t)").WithArguments("(object?, object? t)", "(object, object)").WithLocation(37, 18), // (37,37): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var v5 = ((object, object))(default(T), t); // 10 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(37, 37), // (37,37): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object))(default(T), t); // 10 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(37, 37), // (37,49): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object))(default(T), t); // 10 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(37, 49), // (38,39): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var w5 = ((object?, object?))(default(T), t); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(38, 39)); } [Fact] public void Conversions_ExplicitTupleLiteral_02() { var source = @"#pragma warning disable 0219 interface I { } interface IIn { } interface IOut { } sealed class A : I { } sealed class B : IIn { } sealed class C : IOut { } class D { static void F1(string x, string? y) { var t1 = ((string, string)?)(x, y); // 1 var u1 = ((string?, string?)?)(x, y); var v1 = ((object, object)?)(x, y); // 2 var w1 = ((object?, object?)?)(x, y); } static void F2(A x, A y) { var t2 = ((A, A)?)(x, y); // 3 var u2 = ((A, A)?)(x, y); // 4 var v2 = ((I, I)?)(x, y); // 5 var w2 = ((I, I)?)(x, y); // 6 } static void F3(B x, B y) { var v3 = ((IIn, IIn)?)(x, y); var w3 = ((IIn, IIn)?)(x, y); // 7 } static void F4(C x, C y) { var v4 = ((IOut, IOut)?)(x, y); // 8 var w4 = ((IOut, IOut)?)(x, y); } static void F5(T t) where U : T { var t5 = ((U, U)?)(t, default(T)); // 9 var v5 = ((object, object)?)(default(T), t); // 10 var w5 = ((object?, object?)?)(default(T), t); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,18): warning CS8619: Nullability of reference types in value of type '(string x, string? y)' doesn't match target type '(string, string)?'. // var t1 = ((string, string)?)(x, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((string, string)?)(x, y)").WithArguments("(string x, string? y)", "(string, string)?").WithLocation(12, 18), // (12,41): warning CS8600: Converting null literal or possible null value to non-nullable type. // var t1 = ((string, string)?)(x, y); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(12, 41), // (14,18): warning CS8619: Nullability of reference types in value of type '(object x, object? y)' doesn't match target type '(object, object)?'. // var v1 = ((object, object)?)(x, y); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object)?)(x, y)").WithArguments("(object x, object? y)", "(object, object)?").WithLocation(14, 18), // (14,41): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v1 = ((object, object)?)(x, y); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(14, 41), // (19,47): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // var t2 = ((A, A)?)(x, y); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "A").WithLocation(19, 47), // (20,46): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // var u2 = ((A, A)?)(x, y); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "A").WithLocation(20, 46), // (21,47): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // var v2 = ((I, I)?)(x, y); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "I").WithLocation(21, 47), // (22,46): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // var w2 = ((I, I)?)(x, y); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "I").WithLocation(22, 46), // (27,50): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // var w3 = ((IIn, IIn)?)(x, y); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "IIn").WithLocation(27, 50), // (31,53): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // var v4 = ((IOut, IOut)?)(x, y); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "IOut").WithLocation(31, 53), // (36,28): warning CS8601: Possible null reference assignment. // var t5 = ((U, U)?)(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t").WithLocation(36, 28), // (36,31): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var t5 = ((U, U)?)(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(36, 31), // (36,31): warning CS8601: Possible null reference assignment. // var t5 = ((U, U)?)(t, default(T)); // 9 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "default(T)").WithLocation(36, 31), // (37,18): warning CS8619: Nullability of reference types in value of type '(object?, object? t)' doesn't match target type '(object, object)?'. // var v5 = ((object, object)?)(default(T), t); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object)?)(default(T), t)").WithArguments("(object?, object? t)", "(object, object)?").WithLocation(37, 18), // (37,38): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var v5 = ((object, object)?)(default(T), t); // 10 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(37, 38), // (37,38): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object)?)(default(T), t); // 10 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(37, 38), // (37,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // var v5 = ((object, object)?)(default(T), t); // 10 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(37, 50), // (38,40): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // var w5 = ((object?, object?)?)(default(T), t); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(38, 40)); } [Fact] public void Conversions_ExplicitTuple() { var source = @"#pragma warning disable 0219 interface I { } interface IIn { } interface IOut { } sealed class A : I { } sealed class B : IIn { } sealed class C : IOut { } class D { static void F1((string x, string?) a1) { var t1 = ((string, string))a1; // 1 var u1 = ((string?, string?))a1; var v1 = ((object, object))a1; // 2 var w1 = ((object?, object?))a1; } static void F2((A x, A) a2) { var t2 = ((A, A))a2; // 3 var u2 = ((A, A))a2; // 4 var v2 = ((I, I))a2; // 5 var w2 = ((I, I))a2; // 6 } static void F3((B x, B) a3) { var v3 = ((IIn, IIn))a3; var w3 = ((IIn, IIn))a3; // 7 } static void F4((C x, C) a4) { var v4 = ((IOut, IOut))a4; // 8 var w4 = ((IOut, IOut))a4; } static void F5((T, T) a5) where U : T { var t5 = ((U, U))a5; var v5 = ((object, object))default((T, T)); // 9 var w5 = ((object?, object?))default((T, T)); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,18): warning CS8619: Nullability of reference types in value of type '(string x, string?)' doesn't match target type '(string, string)'. // var t1 = ((string, string))a1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((string, string))a1").WithArguments("(string x, string?)", "(string, string)").WithLocation(12, 18), // (14,18): warning CS8619: Nullability of reference types in value of type '(string x, string?)' doesn't match target type '(object, object)'. // var v1 = ((object, object))a1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object))a1").WithArguments("(string x, string?)", "(object, object)").WithLocation(14, 18), // (19,18): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(A, A)'. // var t2 = ((A, A))a2; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((A, A))a2").WithArguments("(A x, A)", "(A, A)").WithLocation(19, 18), // (20,18): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(A, A)'. // var u2 = ((A, A))a2; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((A, A))a2").WithArguments("(A x, A)", "(A, A)").WithLocation(20, 18), // (21,18): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(I, I)'. // var v2 = ((I, I))a2; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((I, I))a2").WithArguments("(A x, A)", "(I, I)").WithLocation(21, 18), // (22,18): warning CS8619: Nullability of reference types in value of type '(A x, A)' doesn't match target type '(I, I)'. // var w2 = ((I, I))a2; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((I, I))a2").WithArguments("(A x, A)", "(I, I)").WithLocation(22, 18), // (27,18): warning CS8619: Nullability of reference types in value of type '(B x, B)' doesn't match target type '(IIn, IIn)'. // var w3 = ((IIn, IIn))a3; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((IIn, IIn))a3").WithArguments("(B x, B)", "(IIn, IIn)").WithLocation(27, 18), // (31,18): warning CS8619: Nullability of reference types in value of type '(C x, C)' doesn't match target type '(IOut, IOut)'. // var v4 = ((IOut, IOut))a4; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((IOut, IOut))a4").WithArguments("(C x, C)", "(IOut, IOut)").WithLocation(31, 18), // (37,18): warning CS8619: Nullability of reference types in value of type '(T, T)' doesn't match target type '(object, object)'. // var v5 = ((object, object))default((T, T)); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, object))default((T, T))").WithArguments("(T, T)", "(object, object)").WithLocation(37, 18)); } [Fact] [WorkItem(29966, "https://github.com/dotnet/roslyn/issues/29966")] public void Conversions_ImplicitTupleLiteral_ExtensionThis() { var source = @"interface I { } interface IIn { } interface IOut { } class A : I { } class B : IIn { } class C : IOut { } static class E { static void F1(string x, string? y) { (x, y).F1A(); // 1 (x, y).F1B(); } static void F1A(this (object, object) t) { } static void F1B(this (object?, object?) t) { } static void F2(A x, A y) { (x, y).F2A(); // 2 (x, y).F2B(); // 3 } static void F2A(this (I, I) t) { } static void F2B(this (I, I) t) { } static void F3(B x, B y) { (x, y).F3A(); (x, y).F3B(); // 4 } static void F3A(this (IIn, IIn) t) { } static void F3B(this (IIn, IIn) t) { } static void F4(C x, C y) { (x, y).F4A(); // 5 (x, y).F4B(); } static void F4A(this (IOut, IOut) t) { } static void F4B(this (IOut, IOut) t) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29966: Report WRN_NullabilityMismatchInArgument rather than ...Assignment. comp.VerifyDiagnostics( // (11,9): warning CS8620: Nullability of reference types in argument of type '(object x, object? y)' doesn't match target type '(object, object)' for parameter 't' in 'void E.F1A((object, object) t)'. // (x, y).F1A(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(x, y)").WithArguments("(object x, object? y)", "(object, object)", "t", "void E.F1A((object, object) t)").WithLocation(11, 9), // (18,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // (x, y).F2A(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "I").WithLocation(18, 13), // (19,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // (x, y).F2B(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("A", "I").WithLocation(19, 10), // (26,10): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // (x, y).F3B(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("B", "IIn").WithLocation(26, 10), // (32,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // (x, y).F4A(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("C", "IOut").WithLocation(32, 13)); } [Fact] public void Conversions_ImplicitTuple_ExtensionThis_01() { var source = @"interface I { } interface IIn { } interface IOut { } class A : I { } class B : IIn { } class C : IOut { } static class E { static void F1((string x, string?) t1) { t1.F1A(); // 1 t1.F1B(); } static void F1A(this (object, object) t) { } static void F1B(this (object?, object?) t) { } static void F2((A, A) t2) { t2.F2A(); // 2 t2.F2B(); // 3 } static void F2A(this (I, I) t) { } static void F2B(this (I, I) t) { } static void F3((B, B) t3) { t3.F3A(); t3.F3B(); // 4 } static void F3A(this (IIn, IIn) t) { } static void F3B(this (IIn, IIn) t) { } static void F4((C, C) t4) { t4.F4A(); // 5 t4.F4B(); } static void F4A(this (IOut, IOut) t) { } static void F4B(this (IOut, IOut) t) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8620: Nullability of reference types in argument of type '(string x, string?)' doesn't match target type '(object, object)' for parameter 't' in 'void E.F1A((object, object) t)'. // t1.F1A(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t1").WithArguments("(string x, string?)", "(object, object)", "t", "void E.F1A((object, object) t)").WithLocation(11, 9), // (18,9): warning CS8620: Nullability of reference types in argument of type '(A, A)' doesn't match target type '(I, I)' for parameter 't' in 'void E.F2A((I, I) t)'. // t2.F2A(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t2").WithArguments("(A, A)", "(I, I)", "t", "void E.F2A((I, I) t)").WithLocation(18, 9), // (19,9): warning CS8620: Nullability of reference types in argument of type '(A, A)' doesn't match target type '(I, I)' for parameter 't' in 'void E.F2B((I, I) t)'. // t2.F2B(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t2").WithArguments("(A, A)", "(I, I)", "t", "void E.F2B((I, I) t)").WithLocation(19, 9), // (26,9): warning CS8620: Nullability of reference types in argument of type '(B, B)' doesn't match target type '(IIn, IIn)' for parameter 't' in 'void E.F3B((IIn, IIn) t)'. // t3.F3B(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t3").WithArguments("(B, B)", "(IIn, IIn)", "t", "void E.F3B((IIn, IIn) t)").WithLocation(26, 9), // (32,9): warning CS8620: Nullability of reference types in argument of type '(C, C)' doesn't match target type '(IOut, IOut)' for parameter 't' in 'void E.F4A((IOut, IOut) t)'. // t4.F4A(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t4").WithArguments("(C, C)", "(IOut, IOut)", "t", "void E.F4A((IOut, IOut) t)").WithLocation(32, 9)); } [Fact] public void Conversions_ImplicitTuple_ExtensionThis_02() { var source = @"interface I { } interface IIn { } interface IOut { } static class E { static void F1((string, string)? t1) { t1.F1A(); // 1 t1.F1B(); } static void F1A(this (string?, string?)? t) { } static void F1B(this (string, string)? t) { } static void F2((I, I)? t2) { t2.F2A(); t2.F2B(); // 2 } static void F2A(this (I, I)? t) { } static void F2B(this (I, I)? t) { } static void F3((IIn, IIn)? t3) { t3.F3A(); t3.F3B(); // 3 } static void F3A(this (IIn, IIn)? t) { } static void F3B(this (IIn, IIn)? t) { } static void F4((IOut, IOut)? t4) { t4.F4A(); t4.F4B(); // 4 } static void F4A(this (IOut, IOut)? t) { } static void F4B(this (IOut, IOut)? t) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8620: Nullability of reference types in argument of type '(string, string)?' doesn't match target type '(string?, string?)?' for parameter 't' in 'void E.F1A((string?, string?)? t)'. // t1.F1A(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t1").WithArguments("(string, string)?", "(string?, string?)?", "t", "void E.F1A((string?, string?)? t)").WithLocation(8, 9), // (16,9): warning CS8620: Nullability of reference types in argument of type '(I, I)?' doesn't match target type '(I, I)?' for parameter 't' in 'void E.F2B((I, I)? t)'. // t2.F2B(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t2").WithArguments("(I, I)?", "(I, I)?", "t", "void E.F2B((I, I)? t)").WithLocation(16, 9), // (23,9): warning CS8620: Nullability of reference types in argument of type '(IIn, IIn)?' doesn't match target type '(IIn, IIn)?' for parameter 't' in 'void E.F3B((IIn, IIn)? t)'. // t3.F3B(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t3").WithArguments("(IIn, IIn)?", "(IIn, IIn)?", "t", "void E.F3B((IIn, IIn)? t)").WithLocation(23, 9), // (30,9): warning CS8620: Nullability of reference types in argument of type '(IOut, IOut)?' doesn't match target type '(IOut, IOut)?' for parameter 't' in 'void E.F4B((IOut, IOut)? t)'. // t4.F4B(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t4").WithArguments("(IOut, IOut)?", "(IOut, IOut)?", "t", "void E.F4B((IOut, IOut)? t)").WithLocation(30, 9)); } [Fact] public void Conversions_ImplicitTuple_ExtensionThis_03() { var source = @"static class E { static void F((string, (string, string)?) t) { t.FA(); // 1 t.FB(); FA(t); FB(t); } static void FA(this (object, (string?, string?)?) t) { } static void FB(this (object, (string, string)?) t) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8620: Nullability of reference types in argument of type '(string, (string, string)?)' doesn't match target type '(object, (string?, string?)?)' for parameter 't' in 'void E.FA((object, (string?, string?)?) t)'. // t.FA(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t").WithArguments("(string, (string, string)?)", "(object, (string?, string?)?)", "t", "void E.FA((object, (string?, string?)?) t)").WithLocation(5, 9)); } [Fact] public void TupleTypeInference_01() { var source = @"class C { static (T, T) F((T, T) t) => t; static void G(string x, string? y) { F((x, x)).Item2.ToString(); F((x, y)).Item2.ToString(); F((y, x)).Item2.ToString(); F((y, y)).Item2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // F((x, y)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F((x, y)).Item2").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // F((y, x)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F((y, x)).Item2").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // F((y, y)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F((y, y)).Item2").WithLocation(9, 9)); } [Fact] public void TupleTypeInference_02() { var source = @"class C { static (T, T) F((T, T?) t) where T : class => (t.Item1, t.Item1); static void G(string x, string? y) { F((x, x)).Item2.ToString(); F((x, y)).Item2.ToString(); F((y, x)).Item2.ToString(); F((y, y)).Item2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.F((T, T?))'. Nullability of type argument 'string?' doesn't match 'class' constraint. // F((y, x)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F((T, T?))", "T", "string?").WithLocation(8, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // F((y, x)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F((y, x)).Item2").WithLocation(8, 9), // (9,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.F((T, T?))'. Nullability of type argument 'string?' doesn't match 'class' constraint. // F((y, y)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F((T, T?))", "T", "string?").WithLocation(9, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // F((y, y)).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F((y, y)).Item2").WithLocation(9, 9)); } [Fact] public void TupleTypeInference_03() { var source = @"class C { static T F((T, T?) t) where T : class => t.Item1; static void G((string, string) x, (string, string?) y, (string?, string) z, (string?, string?) w) { F(x).ToString(); F(y).ToString(); F(z).ToString(); F(w).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.F((T, T?))'. Nullability of type argument 'string?' doesn't match 'class' constraint. // F(z).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F((T, T?))", "T", "string?").WithLocation(8, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // F(z).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(z)").WithLocation(8, 9), // (9,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.F((T, T?))'. Nullability of type argument 'string?' doesn't match 'class' constraint. // F(w).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F((T, T?))", "T", "string?").WithLocation(9, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // F(w).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(w)").WithLocation(9, 9)); } [Fact] public void TupleTypeInference_04_Ref() { var source = @"class C { static T F(ref (T, T?) t) where T : class => throw new System.Exception(); static void G(string x, string? y) { (string, string) t1 = (x, x); F(ref t1).ToString(); (string, string?) t2 = (x, y); F(ref t2).ToString(); (string?, string) t3 = (y, x); F(ref t3).ToString(); (string?, string?) t4 = (y, y); F(ref t4).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,15): warning CS8620: Argument of type '(string, string)' cannot be used as an input of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. // F(ref t1).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t1").WithArguments("(string, string)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(7, 15), // (11,15): warning CS8620: Argument of type '(string?, string)' cannot be used as an input of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. // F(ref t3).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t3").WithArguments("(string?, string)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(11, 15), // (13,15): warning CS8620: Argument of type '(string?, string?)' cannot be used as an input of type '(string, string?)' for parameter 't' in 'string C.F(ref (string, string?) t)' due to differences in the nullability of reference types. // F(ref t4).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(ref (string, string?) t)").WithLocation(13, 15)); } [Fact] public void TupleTypeInference_04_Out() { var source = @"class C { static T F(out (T, T?) t) where T : class => throw new System.Exception(); static void G() { F(out (string, string) t1).ToString(); F(out (string, string?) t2).ToString(); F(out (string?, string) t3).ToString(); F(out (string?, string?) t4).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): warning CS8624: Argument of type '(string, string)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(out (string, string?) t)' due to differences in the nullability of reference types. // F(out (string, string) t1).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "(string, string) t1").WithArguments("(string, string)", "(string, string?)", "t", "string C.F(out (string, string?) t)").WithLocation(6, 15), // (8,15): warning CS8624: Argument of type '(string?, string)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(out (string, string?) t)' due to differences in the nullability of reference types. // F(out (string?, string) t3).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "(string?, string) t3").WithArguments("(string?, string)", "(string, string?)", "t", "string C.F(out (string, string?) t)").WithLocation(8, 15), // (9,15): warning CS8624: Argument of type '(string?, string?)' cannot be used as an output of type '(string, string?)' for parameter 't' in 'string C.F(out (string, string?) t)' due to differences in the nullability of reference types. // F(out (string?, string?) t4).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "(string?, string?) t4").WithArguments("(string?, string?)", "(string, string?)", "t", "string C.F(out (string, string?) t)").WithLocation(9, 15)); } [Fact] public void TupleTypeInference_05() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static T F(I<(T, T?)> t) where T : class => throw new System.Exception(); static void G(I<(string, string)> x, I<(string, string?)> y, I<(string?, string)> z, I<(string?, string?)> w) { F(x).ToString(); F(y).ToString(); F(z).ToString(); F(w).ToString(); } static T F(IIn<(T, T?)> t) where T : class => throw new System.Exception(); static void G(IIn<(string, string)> x, IIn<(string, string?)> y, IIn<(string?, string)> z, IIn<(string?, string?)> w) { F(x).ToString(); F(y).ToString(); F(z).ToString(); F(w).ToString(); } static T F(IOut<(T, T?)> t) where T : class => throw new System.Exception(); static void G(IOut<(string, string)> x, IOut<(string, string?)> y, IOut<(string?, string)> z, IOut<(string?, string?)> w) { F(x).ToString(); F(y).ToString(); F(z).ToString(); F(w).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): warning CS8620: Nullability of reference types in argument of type 'I<(string, string)>' doesn't match target type 'I<(string, string?)>' for parameter 't' in 'string C.F(I<(string, string?)> t)'. // F(x).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I<(string, string)>", "I<(string, string?)>", "t", "string C.F(I<(string, string?)> t)").WithLocation(9, 11), // (11,11): warning CS8620: Nullability of reference types in argument of type 'I<(string?, string)>' doesn't match target type 'I<(string, string?)>' for parameter 't' in 'string C.F(I<(string, string?)> t)'. // F(z).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("I<(string?, string)>", "I<(string, string?)>", "t", "string C.F(I<(string, string?)> t)").WithLocation(11, 11), // (12,11): warning CS8620: Nullability of reference types in argument of type 'I<(string?, string?)>' doesn't match target type 'I<(string, string?)>' for parameter 't' in 'string C.F(I<(string, string?)> t)'. // F(w).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "w").WithArguments("I<(string?, string?)>", "I<(string, string?)>", "t", "string C.F(I<(string, string?)> t)").WithLocation(12, 11), // (17,11): warning CS8620: Nullability of reference types in argument of type 'IIn<(string, string)>' doesn't match target type 'IIn<(string, string?)>' for parameter 't' in 'string C.F(IIn<(string, string?)> t)'. // F(x).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IIn<(string, string)>", "IIn<(string, string?)>", "t", "string C.F(IIn<(string, string?)> t)").WithLocation(17, 11), // (19,11): warning CS8620: Nullability of reference types in argument of type 'IIn<(string?, string)>' doesn't match target type 'IIn<(string, string?)>' for parameter 't' in 'string C.F(IIn<(string, string?)> t)'. // F(z).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IIn<(string?, string)>", "IIn<(string, string?)>", "t", "string C.F(IIn<(string, string?)> t)").WithLocation(19, 11), // (20,11): warning CS8620: Nullability of reference types in argument of type 'IIn<(string?, string?)>' doesn't match target type 'IIn<(string, string?)>' for parameter 't' in 'string C.F(IIn<(string, string?)> t)'. // F(w).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "w").WithArguments("IIn<(string?, string?)>", "IIn<(string, string?)>", "t", "string C.F(IIn<(string, string?)> t)").WithLocation(20, 11), // (25,11): warning CS8620: Nullability of reference types in argument of type 'IOut<(string, string)>' doesn't match target type 'IOut<(string, string?)>' for parameter 't' in 'string C.F(IOut<(string, string?)> t)'. // F(x).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IOut<(string, string)>", "IOut<(string, string?)>", "t", "string C.F(IOut<(string, string?)> t)").WithLocation(25, 11), // (27,11): warning CS8620: Nullability of reference types in argument of type 'IOut<(string?, string)>' doesn't match target type 'IOut<(string, string?)>' for parameter 't' in 'string C.F(IOut<(string, string?)> t)'. // F(z).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IOut<(string?, string)>", "IOut<(string, string?)>", "t", "string C.F(IOut<(string, string?)> t)").WithLocation(27, 11), // (28,11): warning CS8620: Nullability of reference types in argument of type 'IOut<(string?, string?)>' doesn't match target type 'IOut<(string, string?)>' for parameter 't' in 'string C.F(IOut<(string, string?)> t)'. // F(w).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "w").WithArguments("IOut<(string?, string?)>", "IOut<(string, string?)>", "t", "string C.F(IOut<(string, string?)> t)").WithLocation(28, 11) ); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void TupleTypeInference_06() { var source = @"class C { static void F(object? x, object? y) { if (y != null) { ((object? x, object? y), object? z) t = ((x, y), y); t.Item1.Item1.ToString(); t.Item1.Item2.ToString(); t.Item2.ToString(); t.Item1.x.ToString(); // warning already reported for t.Item1.Item1 t.Item1.y.ToString(); // warning already reported for t.Item1.Item2 t.z.ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // t.Item1.Item1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.Item1").WithLocation(8, 13)); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void TupleTypeInference_07() { var source = @"class C { static void F(object? x, object? y) { if (y != null) { (object? _1, object? _2, object? _3, object? _4, object? _5, object? _6, object? _7, object? _8, object? _9, object? _10) t = (null, null, null, null, null, null, null, x, null, y); t._7.ToString(); t._8.ToString(); t.Rest.Item1.ToString(); // warning already reported for t._8 t.Rest.Item2.ToString(); t._9.ToString(); // warning already reported for t.Rest.Item2 t._10.ToString(); t.Rest.Item3.ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // t._7.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t._7").WithLocation(8, 13), // (9,13): warning CS8602: Dereference of a possibly null reference. // t._8.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t._8").WithLocation(9, 13), // (11,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(11, 13)); } [Fact] [WorkItem(35157, "https://github.com/dotnet/roslyn/issues/35157")] public void TupleTypeInference_08() { var source = @" class C { void M() { _ = (null, 2); _ = (null, (2, 3)); _ = (null, (null, (2, 3))); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): error CS8183: Cannot infer the type of implicitly-typed discard. // _ = (null, 2); Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(6, 9), // (7,9): error CS8183: Cannot infer the type of implicitly-typed discard. // _ = (null, (2, 3)); Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(7, 9), // (8,9): error CS8183: Cannot infer the type of implicitly-typed discard. // _ = (null, (null, (2, 3))); Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(8, 9) ); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_01() { var source = @"class Program { static void F() { (object? a, string) t = (default(object), default(string)) /*T:(object?, string?)*/; // 1 (object, string? b) u = t; // 2 _ = t/*T:(object? a, string!)*/; _ = u/*T:(object!, string? b)*/; t.Item1.ToString(); // 3 t.Item2.ToString(); // 4 u.Item1.ToString(); // 5 u.Item2.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,33): warning CS8619: Nullability of reference types in value of type '(object?, string?)' doesn't match target type '(object? a, string)'. // (object? a, string) t = (default(object), default(string)) /*T:(object?, string?)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default(object), default(string))").WithArguments("(object?, string?)", "(object? a, string)").WithLocation(5, 33), // (6,33): warning CS8619: Nullability of reference types in value of type '(object? a, string)' doesn't match target type '(object, string? b)'. // (object, string? b) u = t; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("(object? a, string)", "(object, string? b)").WithLocation(6, 33), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2").WithLocation(12, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_02() { var source = @"class Program { static void F(object? x, object y) { (object x, object? y, object? z) t = (null, x, y); // 1 _ = t/*T:(object! x, object? y, object? z)*/; t.x.ToString(); // 2 t.y.ToString(); // 3 t.z.ToString(); if (x == null) return; (object x, object y) u = (x, default(object))/*T:(object! x, object?)*/; // 4 _ = u/*T:(object! x, object! y)*/; u.x.ToString(); u.y.ToString(); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (5,46): warning CS8619: Nullability of reference types in value of type '(object?, object? x, object y)' doesn't match target type '(object x, object? y, object? z)'. // (object x, object? y, object? z) t = (null, x, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, x, y)").WithArguments("(object?, object? x, object y)", "(object x, object? y, object? z)").WithLocation(5, 46), // (7,9): warning CS8602: Dereference of a possibly null reference. // t.x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.x").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(8, 9), // (11,34): warning CS8619: Nullability of reference types in value of type '(object x, object?)' doesn't match target type '(object x, object y)'. // (object x, object y) u = (x, default(object))/*T:(object! x, object?)*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, default(object))").WithArguments("(object x, object?)", "(object x, object y)").WithLocation(11, 34), // (14,9): warning CS8602: Dereference of a possibly null reference. // u.y.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(14, 9)); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_03() { var source = @"class A { internal object? F; } class B : A { } class Program { static void F1() { (A, A?) t1 = (null, new A() { F = 1 }); // 1 (A x, A? y) u1 = t1; u1.x.ToString(); // 2 u1.y.ToString(); u1.y.F.ToString(); } static void F2() { (A, A?) t2 = (null, new B() { F = 2 }); // 3 (A x, A? y) u2 = t2; u2.x.ToString(); // 4 u2.y.ToString(); u2.y.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,22): warning CS8619: Nullability of reference types in value of type '(A?, A)' doesn't match target type '(A, A?)'. // (A, A?) t1 = (null, new A() { F = 1 }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, new A() { F = 1 })").WithArguments("(A?, A)", "(A, A?)").WithLocation(12, 22), // (14,9): warning CS8602: Dereference of a possibly null reference. // u1.x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u1.x").WithLocation(14, 9), // (20,22): warning CS8619: Nullability of reference types in value of type '(A?, A)' doesn't match target type '(A, A?)'. // (A, A?) t2 = (null, new B() { F = 2 }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, new B() { F = 2 })").WithArguments("(A?, A)", "(A, A?)").WithLocation(20, 22), // (22,9): warning CS8602: Dereference of a possibly null reference. // u2.x.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2.x").WithLocation(22, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_04() { var source = @"class Program { static void F(object? x, string? y) { (object?, string) t = (x, y)/*T:(object? x, string? y)*/; // 1 (object, string?) u = t; // 2 t.Item1.ToString(); // 3 t.Item2.ToString(); // 4 u.Item1.ToString(); // 5 u.Item2.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,31): warning CS8619: Nullability of reference types in value of type '(object? x, string? y)' doesn't match target type '(object?, string)'. // (object?, string) t = (x, y)/*T:(object? x, string? y)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(object? x, string? y)", "(object?, string)").WithLocation(5, 31), // (6,31): warning CS8619: Nullability of reference types in value of type '(object?, string)' doesn't match target type '(object, string?)'. // (object, string?) u = t; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("(object?, string)", "(object, string?)").WithLocation(6, 31), // (7,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2").WithLocation(10, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_05() { var source = @"class Program { static void F(object x, string? y) { (object?, string) t = (x, y)/*T:(object! x, string? y)*/; // 1 (object a, string? b) u = t; // 2 t.Item1.ToString(); t.Item2.ToString(); // 3 u.Item1.ToString(); u.Item2.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,31): warning CS8619: Nullability of reference types in value of type '(object x, string? y)' doesn't match target type '(object?, string)'. // (object?, string) t = (x, y)/*T:(object! x, string? y)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(object x, string? y)", "(object?, string)").WithLocation(5, 31), // (6,35): warning CS8619: Nullability of reference types in value of type '(object?, string)' doesn't match target type '(object a, string? b)'. // (object a, string? b) u = t; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("(object?, string)", "(object a, string? b)").WithLocation(6, 35), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2").WithLocation(10, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_06() { var source = @"class Program { static void F(string x, string? y) { (object, string) t = ((object, string))(x, y)/*T:(string! x, string? y)*/; // 1 (object a, string?) u = ((string, string?))t; (object?, object b) v = ((object?, object))t; t.Item1.ToString(); t.Item2.ToString(); // 2 u.Item1.ToString(); u.Item2.ToString(); // 3 v.Item1.ToString(); v.Item2.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,30): warning CS8619: Nullability of reference types in value of type '(object x, string? y)' doesn't match target type '(object, string)'. // (object, string) t = ((object, string))(x, y)/*T:(object! x, string? y)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((object, string))(x, y)").WithArguments("(object x, string? y)", "(object, string)").WithLocation(5, 30), // (5,52): warning CS8600: Converting null literal or possible null value to non-nullable type. // (object, string) t = ((object, string))(x, y)/*T:(object! x, string? y)*/; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(5, 52), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2").WithLocation(11, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // v.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v.Item2").WithLocation(13, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_07() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { internal T F; } class Program { static void F(C x, C y) { if (y.F == null) return; var t = (x, y); var u = t; t.Item1.F.ToString(); // 1 t.Item2.F.ToString(); u.Item1.F.ToString(); // 2 u.Item2.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.F").WithLocation(14, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1.F").WithLocation(16, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_08() { var source = @"class Program { static void F(bool b, object x, object? y) { (object?, object, object?, object, object?, (object, object?), object, object, object?, object) t = (x, x, x, y, y, (y, x), x, x, y, y)/*T:(object!, object!, object!, object?, object?, (object? y, object! x), object!, object!, object?, object?)*/; // 1 t.Item1.ToString(); t.Item2.ToString(); t.Item3.ToString(); t.Item4.ToString(); // 2 t.Item5.ToString(); // 3 t.Item6.Item1.ToString(); // 4 t.Item6.Item2.ToString(); t.Item7.ToString(); if (b) { t.Item8.ToString(); t.Item9.ToString(); // 5 t.Item10.ToString(); // 6 } else { t.Rest.Item1.ToString(); t.Rest.Item2.ToString(); // 7 t.Rest.Item3.ToString(); // 8 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8619: Nullability of reference types in value of type '(object, object, object, object?, object?, (object? y, object x), object, object, object?, object?)' doesn't match target type '(object?, object, object?, object, object?, (object, object?), object, object, object?, object)'. // (x, x, x, y, y, (y, x), x, x, y, y)/*T:(object!, object!, object!, object?, object?, (object? y, object! x), object!, object!, object?, object?)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, x, x, y, y, (y, x), x, x, y, y)").WithArguments("(object, object, object, object?, object?, (object? y, object x), object, object, object?, object?)", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object)").WithLocation(6, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // t.Item4.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item4").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // t.Item5.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item5").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item1").WithLocation(12, 9), // (18,13): warning CS8602: Dereference of a possibly null reference. // t.Item9.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item9").WithLocation(18, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // t.Item10.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item10").WithLocation(19, 13), // (24,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(24, 13), // (25,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item3.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item3").WithLocation(25, 13)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_09() { var source = @"class Program { static void F(bool b, object x) { (object?, object, object?, object, object?, (object, object?), object, object, object?, object) t = (x, x, x, default(object), default(object), default((object, object?)), x, x, default(object), default(object))/*T:(object!, object!, object!, object?, object?, (object!, object?), object!, object!, object?, object?)*/; // 1 t.Item1.ToString(); t.Item2.ToString(); t.Item3.ToString(); t.Item4.ToString(); // 2 t.Item5.ToString(); // 3 t.Item6.Item1.ToString(); // 4 t.Item6.Item2.ToString(); // 5 t.Item7.ToString(); if (b) { t.Item8.ToString(); t.Item9.ToString(); // 6 t.Item10.ToString(); // 7 } else { t.Rest.Item1.ToString(); t.Rest.Item2.ToString(); // 8 t.Rest.Item3.ToString(); // 9 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8619: Nullability of reference types in value of type '(object, object, object, object?, object?, (object, object?), object, object, object?, object?)' doesn't match target type '(object?, object, object?, object, object?, (object, object?), object, object, object?, object)'. // (x, x, x, default(object), default(object), default((object, object?)), x, x, default(object), default(object))/*T:(object!, object!, object!, object?, object?, (object!, object?), object!, object!, object?, object?)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, x, x, default(object), default(object), default((object, object?)), x, x, default(object), default(object))").WithArguments("(object, object, object, object?, object?, (object, object?), object, object, object?, object?)", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object)").WithLocation(6, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // t.Item4.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item4").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // t.Item5.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item5").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item1").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item2").WithLocation(13, 9), // (18,13): warning CS8602: Dereference of a possibly null reference. // t.Item9.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item9").WithLocation(18, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // t.Item10.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item10").WithLocation(19, 13), // (24,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(24, 13), // (25,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item3.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item3").WithLocation(25, 13)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_10() { // https://github.com/dotnet/roslyn/issues/35010: LValueType.TypeSymbol and RValueType.Type do not agree for the null literal var source = @"using System; class Program { static void F(object x, string y) { (object, string?) t = new ValueTuple(null, """") { Item1 = x }; // 1 (object?, string) u = new ValueTuple() { Item2 = y }; t.Item1.ToString(); t.Item2.ToString(); u.Item1.ToString(); // 2 u.Item1.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,31): warning CS8619: Nullability of reference types in value of type '(object?, string)' doesn't match target type '(object, string?)'. // (object, string?) t = new ValueTuple(null, "") { Item1 = x }; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, @"new ValueTuple(null, """") { Item1 = x }").WithArguments("(object?, string)", "(object, string?)").WithLocation(6, 31), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(10, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_11() { var source = @"using System; class Program { static void F(bool b, object x, object? y) { var t = new ValueTuple, object, ValueTuple>( x, x, x, y, // 1 y, new ValueTuple(y, x), // 2 x, new ValueTuple(x, y, y))/*T:(object?, object!, object?, object!, object?, (object!, object?), object!, object!, object?, object!)*/; // 3 t.Item1.ToString(); t.Item2.ToString(); t.Item3.ToString(); t.Item4.ToString(); // 4 t.Item5.ToString(); // 5 t.Item6.Item1.ToString(); // 6 t.Item6.Item2.ToString(); t.Item7.ToString(); if (b) { t.Item8.ToString(); t.Item9.ToString(); // 7 t.Item10.ToString(); // 8 } else { t.Rest.Item1.ToString(); t.Rest.Item2.ToString(); // 9 t.Rest.Item3.ToString(); // 10 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8604: Possible null reference argument for parameter 'item4' in '(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)'. // y, // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("item4", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)").WithLocation(10, 13), // (12,45): warning CS8604: Possible null reference argument for parameter 'item1' in '(object, object?).(object item1, object? item2)'. // new ValueTuple(y, x), // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("item1", "(object, object?).(object item1, object? item2)").WithLocation(12, 45), // (14,59): warning CS8604: Possible null reference argument for parameter 'item3' in '(object, object?, object).(object item1, object? item2, object item3)'. // new ValueTuple(x, y, y))/*T:(object?, object!, object?, object!, object?, (object!, object?), object!, object!, object?, object!)*/; // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("item3", "(object, object?, object).(object item1, object? item2, object item3)").WithLocation(14, 59), // (18,9): warning CS8602: Dereference of a possibly null reference. // t.Item4.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item4").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // t.Item5.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item5").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item1.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item1").WithLocation(20, 9), // (26,13): warning CS8602: Dereference of a possibly null reference. // t.Item9.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item9").WithLocation(26, 13), // (27,13): warning CS8602: Dereference of a possibly null reference. // t.Item10.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item10").WithLocation(27, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(32, 13), // (33,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item3.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item3").WithLocation(33, 13)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_12() { var source = @"using System; class Program { static void F(bool b, object x) { var t = new ValueTuple, object, ValueTuple>( x, x, x, default, // 1 default, default, x, default)/*T:(object?, object!, object?, object!, object?, (object!, object?), object!, object!, object?, object!)*/; t.Item1.ToString(); t.Item2.ToString(); t.Item3.ToString(); t.Item4.ToString(); // 2 t.Item5.ToString(); // 3 t.Item6.Item1.ToString(); // 4 t.Item6.Item2.ToString(); // 5 t.Item7.ToString(); if (b) { t.Item8.ToString(); // 6 t.Item9.ToString(); // 7 t.Item10.ToString(); // 8 } else { t.Rest.Item1.ToString(); // 9 t.Rest.Item2.ToString(); // 10 t.Rest.Item3.ToString(); // 11 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // default, // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(10, 13), // (18,9): warning CS8602: Dereference of a possibly null reference. // t.Item4.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item4").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // t.Item5.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item5").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item1").WithLocation(20, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item2").WithLocation(21, 9), // (25,13): warning CS8602: Dereference of a possibly null reference. // t.Item8.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item8").WithLocation(25, 13), // (26,13): warning CS8602: Dereference of a possibly null reference. // t.Item9.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item9").WithLocation(26, 13), // (27,13): warning CS8602: Dereference of a possibly null reference. // t.Item10.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item10").WithLocation(27, 13), // (31,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item1.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item1").WithLocation(31, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(32, 13), // (33,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item3.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item3").WithLocation(33, 13)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_13() { var source = @"using System; class Program { static void F(bool b, object x, object? y) { var t = new ValueTuple( x, x, x, y, // 1 y, (y, x), // 2 x, (x, y, y))/*T:(object?, object!, object?, object!, object?, (object!, object?), object!, object!, object?, object!)*/; // 3 t.Item1.ToString(); t.Item2.ToString(); t.Item3.ToString(); t.Item4.ToString(); // 4 t.Item5.ToString(); // 5 t.Item6.Item1.ToString(); // 6 t.Item6.Item2.ToString(); t.Item7.ToString(); if (b) { t.Item8.ToString(); t.Item9.ToString(); // 7 t.Item10.ToString(); // 8 } else { t.Rest.Item1.ToString(); t.Rest.Item2.ToString(); // 9 t.Rest.Item3.ToString(); // 10 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8604: Possible null reference argument for parameter 'item4' in '(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)'. // y, // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("item4", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)").WithLocation(10, 13), // (12,13): warning CS8620: Nullability of reference types in argument of type '(object? y, object x)' doesn't match target type '(object, object?)' for parameter 'item6' in '(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)'. // (y, x), // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, x)").WithArguments("(object? y, object x)", "(object, object?)", "item6", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)").WithLocation(12, 13), // (14,13): warning CS8620: Nullability of reference types in argument of type '(object x, object?, object?)' doesn't match target type '(object, object?, object)' for parameter 'rest' in '(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)'. // (x, y, y))/*T:(object?, object!, object?, object!, object?, (object!, object?), object!, object!, object?, object!)*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(x, y, y)").WithArguments("(object x, object?, object?)", "(object, object?, object)", "rest", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object).(object? item1, object item2, object? item3, object item4, object? item5, (object, object?) item6, object item7, (object, object?, object) rest)").WithLocation(14, 13), // (18,9): warning CS8602: Dereference of a possibly null reference. // t.Item4.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item4").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // t.Item5.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item5").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item1.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item1").WithLocation(20, 9), // (26,13): warning CS8602: Dereference of a possibly null reference. // t.Item9.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item9").WithLocation(26, 13), // (27,13): warning CS8602: Dereference of a possibly null reference. // t.Item10.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item10").WithLocation(27, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(32, 13), // (33,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item3.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item3").WithLocation(33, 13)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_14() { var source = @"using System; class Program { static void F(bool b, object x) { var t = new ValueTuple( x, x, x, default, // 1 default, default, x, default)/*T:(object?, object!, object?, object!, object?, (object!, object?), object!, object!, object?, object!)*/; t.Item1.ToString(); t.Item2.ToString(); t.Item3.ToString(); t.Item4.ToString(); // 2 t.Item5.ToString(); // 3 t.Item6.Item1.ToString(); // 4 t.Item6.Item2.ToString(); // 5 t.Item7.ToString(); if (b) { t.Item8.ToString(); // 6 t.Item9.ToString(); // 7 t.Item10.ToString(); // 8 } else { t.Rest.Item1.ToString(); // 9 t.Rest.Item2.ToString(); // 10 t.Rest.Item3.ToString(); // 11 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // default, // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(10, 13), // (18,9): warning CS8602: Dereference of a possibly null reference. // t.Item4.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item4").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // t.Item5.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item5").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item1").WithLocation(20, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // t.Item6.Item2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item6.Item2").WithLocation(21, 9), // (25,13): warning CS8602: Dereference of a possibly null reference. // t.Item8.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item8").WithLocation(25, 13), // (26,13): warning CS8602: Dereference of a possibly null reference. // t.Item9.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item9").WithLocation(26, 13), // (27,13): warning CS8602: Dereference of a possibly null reference. // t.Item10.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item10").WithLocation(27, 13), // (31,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item1.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item1").WithLocation(31, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item2.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item2").WithLocation(32, 13), // (33,13): warning CS8602: Dereference of a possibly null reference. // t.Rest.Item3.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Rest.Item3").WithLocation(33, 13)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_15() { var source = @"using System; class Program { static void F(object x, string? y) { var t = new ValueTuple(1); var u = new ValueTuple(null, null, 3); t.Item1.ToString(); // 1 t.Item2.ToString(); u.Item1.ToString(); // 2 u.Item1.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,21): error CS7036: There is no argument given that corresponds to the required formal parameter 'item2' of '(object?, string).(object?, string)' // var t = new ValueTuple(1); Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "ValueTuple").WithArguments("item2", "(object?, string).(object?, string)").WithLocation(6, 21), // (7,21): error CS1729: '(object?, string)' does not contain a constructor that takes 3 arguments // var u = new ValueTuple(null, null, 3); Diagnostic(ErrorCode.ERR_BadCtorArgCount, "ValueTuple").WithArguments("(object?, string)", "3").WithLocation(7, 21), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(10, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_16() { var source = @"class Program { static object F(object? x, object y, string z, string w) { throw null!; } static void G(bool b, string s, (string?, string?) t) { (string? x, string? y) u; (string? x, string? y) v; _ = b ? F( t.Item1 = s, u = t, u.x.ToString(), u.y.ToString()) : // 1 F( t.Item2 = s, v = t, v.x.ToString(), // 2 v.y.ToString()); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,17): warning CS8602: Dereference of a possibly null reference. // u.y.ToString()) : // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(16, 17), // (20,17): warning CS8602: Dereference of a possibly null reference. // v.x.ToString(), // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v.x").WithLocation(20, 17)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_17() { var source = @"class C { (object x, (string? z, object w) y) F; static void M(C c, (object? x, (string z, object? w) y) t) { c.F = t; // 1 (object, (string?, object)) u = c.F/*T:(object! x, (string? z, object! w) y)*/; c.F.x.ToString(); // 2 c.F.y.z.ToString(); c.F.y.w.ToString(); // 3 u.Item1.ToString(); // 4 u.Item2.Item1.ToString(); u.Item2.Item2.ToString(); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): warning CS8619: Nullability of reference types in value of type '(object? x, (string z, object? w) y)' doesn't match target type '(object x, (string? z, object w) y)'. // c.F = t; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("(object? x, (string z, object? w) y)", "(object x, (string? z, object w) y)").WithLocation(6, 15), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.F.x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F.x").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // c.F.y.w.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F.y.w").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(11, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.Item2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2.Item2").WithLocation(13, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Tuple_Assignment_18() { var source = @"class Program { static void F(string s) { (object, object?)? t = (null, s); // 1 (object?, object?) u = t.Value; t.Value.Item1.ToString(); // 2 t.Value.Item2.ToString(); u.Item1.ToString(); // 3 u.Item2.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,32): warning CS8619: Nullability of reference types in value of type '(object?, object s)' doesn't match target type '(object, object?)?'. // (object, object?)? t = (null, s); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, s)").WithArguments("(object?, object s)", "(object, object?)?").WithLocation(5, 32), // (7,9): warning CS8602: Dereference of a possibly null reference. // t.Value.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Value.Item1").WithLocation(7, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(9, 9)); } [Fact] public void Tuple_Assignment_19() { var source = @"class C { static void F() { (string, string?) t = t; t.Item1.ToString(); t.Item2.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,31): error CS0165: Use of unassigned local variable 't' // (string, string?) t = t; Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(5, 31), // (7,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(7, 9)); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_20() { var source = @"class C { static void G(object? x, object? y) { F = (x, y); } static (object?, object?) G() { return ((object?, object?))F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS0103: The name 'F' does not exist in the current context // F = (x, y); Diagnostic(ErrorCode.ERR_NameNotInContext, "F").WithArguments("F").WithLocation(5, 9), // (9,36): error CS0103: The name 'F' does not exist in the current context // return ((object?, object?))F; Diagnostic(ErrorCode.ERR_NameNotInContext, "F").WithArguments("F").WithLocation(9, 36)); } [Fact] [WorkItem(35010, "https://github.com/dotnet/roslyn/issues/35010")] public void Tuple_Assignment_21() { var source = @" #pragma warning disable CS0219 class C { static void F(string? x, string? y) { (object a, long b) t = (x, 0)/*T:(string? x, int)*/; // 1 (object a, (long b, object c)) t2 = (x, (0, y)/*T:(int, string? y)*/)/*T:(string? x, (int, string? y))*/; // 2, 3 (object a, (long b, object c)) t3 = (x!, (0, y!)/*T:(int, string!)*/)/*T:(string!, (int, string!))*/; (int b, string? c)? t4 = null; (object? a, (long b, object? c)?) t5 = (x, t4)/*T:(string? x, (int b, string? c)? t4)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,32): warning CS8619: Nullability of reference types in value of type '(object? x, long)' doesn't match target type '(object a, long b)'. // (object a, long b) t = (x, 0)/*T:(string? x, int)*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, 0)").WithArguments("(object? x, long)", "(object a, long b)").WithLocation(7, 32), // (8,45): warning CS8619: Nullability of reference types in value of type '(object? x, (long b, object c))' doesn't match target type '(object a, (long b, object c))'. // (object a, (long b, object c)) t2 = (x, (0, y)/*T:(int, string? y)*/)/*T:(string? x, (int, string! y))*/; // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, (0, y)/*T:(int, string? y)*/)").WithArguments("(object? x, (long b, object c))", "(object a, (long b, object c))").WithLocation(8, 45), // (8,49): warning CS8619: Nullability of reference types in value of type '(long, object? y)' doesn't match target type '(long b, object c)'. // (object a, (long b, object c)) t2 = (x, (0, y)/*T:(int, string? y)*/)/*T:(string? x, (int, string! y))*/; // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(0, y)").WithArguments("(long, object? y)", "(long b, object c)").WithLocation(8, 49) ); comp.VerifyTypes(); } [Fact] [WorkItem(35010, "https://github.com/dotnet/roslyn/issues/35010")] public void Tuple_Assignment_22() { var source = @" #pragma warning disable CS0219 class C { static void F(string? x) { (C, C)/*T:(C!, C!)*/ b = (x, x)/*T:(string?, string?)*/; } public static implicit operator C(string? a) { return new C(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_23() { var source = @"class Program { static void F() { (object? a, string) t = (default, default) /*T:!*/; // 1 (object, string? b) u = t; // 2 _ = t/*T:(object? a, string!)*/; _ = u/*T:(object!, string? b)*/; t.Item1.ToString(); // 3 t.Item2.ToString(); // 4 u.Item1.ToString(); // 5 u.Item2.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,33): warning CS8619: Nullability of reference types in value of type '(object?, string?)' doesn't match target type '(object? a, string)'. // (object? a, string) t = (default, default) /*T:!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default, default)").WithArguments("(object?, string?)", "(object? a, string)").WithLocation(5, 33), // (6,33): warning CS8619: Nullability of reference types in value of type '(object? a, string)' doesn't match target type '(object, string? b)'. // (object, string? b) u = t; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("(object? a, string)", "(object, string? b)").WithLocation(6, 33), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.Item1.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2").WithLocation(12, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] public void Tuple_Assignment_24() { var source = @"class Program { static void F(object? x, object y) { (object x, object? y, object? z) t = (null, x, y); // 1 _ = t/*T:(object! x, object? y, object? z)*/; t.x.ToString(); // 2 t.y.ToString(); // 3 t.z.ToString(); if (x == null) return; (object x, object y) u = (x, default)/*T:!*/; // 4 _ = u/*T:(object! x, object! y)*/; u.x.ToString(); u.y.ToString(); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (5,46): warning CS8619: Nullability of reference types in value of type '(object?, object? x, object y)' doesn't match target type '(object x, object? y, object? z)'. // (object x, object? y, object? z) t = (null, x, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, x, y)").WithArguments("(object?, object? x, object y)", "(object x, object? y, object? z)").WithLocation(5, 46), // (7,9): warning CS8602: Dereference of a possibly null reference. // t.x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.x").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(8, 9), // (11,34): warning CS8619: Nullability of reference types in value of type '(object x, object?)' doesn't match target type '(object x, object y)'. // (object x, object y) u = (x, default)/*T:!*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, default)").WithArguments("(object x, object?)", "(object x, object y)").WithLocation(11, 34), // (14,9): warning CS8602: Dereference of a possibly null reference. // u.y.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(14, 9)); } [Fact] [WorkItem(32338, "https://github.com/dotnet/roslyn/issues/32338")] public void CopyStructUnconstrainedFieldNullability_01() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void M(T t) { var x = new S() { F = t }; var y = x; y.F.ToString(); // 1 if (t == null) return; x = new S() { F = t }; var z = x; z.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(12, 9)); } [Fact] [WorkItem(32338, "https://github.com/dotnet/roslyn/issues/32338")] public void CopyStructUnconstrainedFieldNullability_02() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void M(S x) { var y = x; y.F.ToString(); // 1 if (x.F == null) return; var z = x; z.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(11, 9)); } [Fact] [WorkItem(29970, "https://github.com/dotnet/roslyn/issues/29970")] [WorkItem(32338, "https://github.com/dotnet/roslyn/issues/32338")] public void CopyTupleUnconstrainedElementNullability_01() { var source = @"class Program { static void M(T t, U u) { var x = (t, u); var y = x; y.Item1.ToString(); // 1 if (t == null) return; x = (t, u); var z = x; z.Item1.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // y.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(7, 9)); } [Fact] [WorkItem(32338, "https://github.com/dotnet/roslyn/issues/32338")] public void CopyTupleUnconstrainedElementNullability_02() { var source = @"class Program { static void M((T, U) x) { var y = x; y.Item1.ToString(); // 1 if (x.Item1 == null) return; var z = x; z.Item1.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // y.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(6, 9)); } [Fact] [WorkItem(32703, "https://github.com/dotnet/roslyn/issues/32703")] [WorkItem(31395, "https://github.com/dotnet/roslyn/issues/31395")] public void CopyClassFields() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { internal object? F; internal object G; } class Program { static void F(C x) { if (x.F == null) return; if (x.G != null) return; C y = x; x.F.ToString(); x.G.ToString(); // 1 y.F.ToString(); y.G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,9): warning CS8602: Dereference of a possibly null reference. // x.G.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.G").WithLocation(16, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // y.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.G").WithLocation(18, 9)); } [Fact] [WorkItem(32703, "https://github.com/dotnet/roslyn/issues/32703")] public void CopyStructFields() { var source = @"#pragma warning disable 0649 struct S { internal object? F; internal object G; } class Program { static void F(S x) { if (x.F == null) return; if (x.G != null) return; S y = x; x.F.ToString(); x.G.ToString(); // 1 y.F.ToString(); y.G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // x.G.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.G").WithLocation(15, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // y.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.G").WithLocation(17, 9) ); } [Fact] [WorkItem(32703, "https://github.com/dotnet/roslyn/issues/32703")] public void CopyNullableStructFields() { var source = @"#pragma warning disable 0649 struct S { internal object? F; internal object G; } class Program { static void F(S? x) { if (x == null) return; if (x.Value.F == null) return; if (x.Value.G != null) return; S? y = x; x.Value.F.ToString(); x.Value.G.ToString(); // 1 y.Value.F.ToString(); y.Value.G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,9): warning CS8602: Dereference of a possibly null reference. // x.Value.G.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.G").WithLocation(16, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // y.Value.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.G").WithLocation(18, 9) ); } [Fact] [WorkItem(31395, "https://github.com/dotnet/roslyn/issues/31395")] public void NestedAssignment() { var source = @"class C { internal C? F; internal C G = null!; } class Program { static void F1() { var x1 = new C() { F = new C(), G = null }; // 1 var y1 = new C() { F = x1, G = (x1 = new C()) }; y1.F.F.ToString(); y1.F.G.ToString(); // 2 y1.G.F.ToString(); // 3 y1.G.G.ToString(); } static void F2() { var x2 = new C() { F = new C(), G = null }; // 4 var y2 = new C() { G = x2, F = (x2 = new C()) }; y2.F.F.ToString(); // 5 y2.F.G.ToString(); y2.G.F.ToString(); y2.G.G.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,45): warning CS8625: Cannot convert null literal to non-nullable reference type. // var x1 = new C() { F = new C(), G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 45), // (13,9): warning CS8602: Dereference of a possibly null reference. // y1.F.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1.F.G").WithLocation(13, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // y1.G.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1.G.F").WithLocation(14, 9), // (19,45): warning CS8625: Cannot convert null literal to non-nullable reference type. // var x2 = new C() { F = new C(), G = null }; // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 45), // (21,9): warning CS8602: Dereference of a possibly null reference. // y2.F.F.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2.F.F").WithLocation(21, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // y2.G.G.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2.G.G").WithLocation(24, 9)); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void ConditionalAccessIsAPureTest() { var source = @" class C { void F(object o) { if (o?.ToString() != null) o.ToString(); else o.ToString(); // 1 o.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(9, 13) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void ConditionalAccessIsAPureTest_Generic() { var source = @" class C { void F(T t) { if (t is null) return; if (t?.ToString() != null) t.ToString(); else t.ToString(); // 1 t.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(11, 13) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void ConditionalAccessIsAPureTest_Indexer() { var source = @" class C { void F(C c) { if (c?[0] == true) c.ToString(); else c.ToString(); // 1 c.ToString(); } bool this[int i] => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(9, 13) ); } [Fact] [WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] [WorkItem(34018, "https://github.com/dotnet/roslyn/issues/34018")] public void ConditionalAccessIsAPureTest_InFinally_01() { var source = @" class C { void F(object o) { try { } finally { if (o?.ToString() != null) o.ToString(); } o.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(34018, "https://github.com/dotnet/roslyn/issues/34018")] public void ConditionalAccessIsAPureTest_InFinally_02() { var source = @" class C { void F() { C? c = null; try { c = new C(); } finally { if (c != null) c.Cleanup(); } c.Operation(); // ok } void Cleanup() {} void Operation() {} }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void NullCoalescingIsAPureTest() { var source = @" class C { void F(string s, string s2) { _ = s ?? s.ToString(); // 1 _ = s2 ?? null; s2.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): warning CS8602: Dereference of a possibly null reference. // _ = s ?? s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 18), // (9,9): warning CS8602: Dereference of a possibly null reference. // s2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(9, 9) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void NullCoalescingAssignmentIsAPureTest() { var source = @" class C { void F(string s, string s2) { s ??= s.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,15): warning CS8602: Dereference of a possibly null reference. // s ??= s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(6, 15) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void NullComparisonIsAPureTest() { var source = @" class C { void F(C x, C y) { if (x == null) x.ToString(); // 1 else x.ToString(); if (null != y) y.ToString(); else y.ToString(); // 2 } public static bool operator==(C? one, C? two) => throw null!; public static bool operator!=(C? one, C? two) => throw null!; public override bool Equals(object o) => throw null!; public override int GetHashCode() => throw null!; }"; // `x == null` is a "pure test" even when it binds to a user-defined operator, // so affects both branches var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(14, 13) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void NullComparisonIsAPureTest_IntroducesMaybeNull() { var source = @" class C { void F(C x, C y) { if (x == null) { } x.ToString(); // 1 if (null != y) { } y.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(10, 9) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void NullComparisonIsAPureTest_WithCast() { var source = @" class C { void F(object x, object y) { if ((string)x == null) x.ToString(); // 1 else x.ToString(); if (null != (string)y) y.ToString(); else y.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(14, 13) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void IsNullIsAPureTest() { var source = @" class C { void F(C x) { if (x is null) x.ToString(); // 1 else x.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 13) ); } [Fact, WorkItem(33526, "https://github.com/dotnet/roslyn/issues/33526")] public void OtherComparisonsAreNotPureTest() { var source = @" class C { void F(C x) { if (x is object) { } x.ToString(); if (x is object y) { } x.ToString(); if (x is object _) { } x.ToString(); if (x is D) { } x.ToString(); if (x is {}) { } x.ToString(); } } class D : C { } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ImplicitNullable_01() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { S? x = new S() { F = 1, G = null }; // 1 S? y = x; x.Value.F.ToString(); x.Value.G.ToString(); // 2 y.Value.F.ToString(); y.Value.G.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S? x = new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 37), // (13,9): warning CS8602: Dereference of a possibly null reference. // x.Value.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.G").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.Value.G.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.G").WithLocation(15, 9)); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ImplicitNullable_02() { var source = @"class Program { static void F(int? x) { long? y = x; if (x == null) return; long? z = x; x.Value.ToString(); y.Value.ToString(); // 1 z.Value.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8629: Nullable value type may be null. // y.Value.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(9, 9) ); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ImplicitNullable_03() { var source = @"class Program { static void F(int x) { int? y = x; long? z = x; y.Value.ToString(); z.Value.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ImplicitNullable_04() { var source = @"class Program { static void F1(long x1) { int? y1 = x1; // 1 y1.Value.ToString(); } static void F2(long? x2) { int? y2 = x2; // 2 y2.Value.ToString(); // 3 } static void F3(long? x3) { if (x3 == null) return; int? y3 = x3; // 4 y3.Value.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,19): error CS0266: Cannot implicitly convert type 'long' to 'int?'. An explicit conversion exists (are you missing a cast?) // int? y1 = x1; // 1 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x1").WithArguments("long", "int?").WithLocation(5, 19), // (10,19): error CS0266: Cannot implicitly convert type 'long?' to 'int?'. An explicit conversion exists (are you missing a cast?) // int? y2 = x2; // 2 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x2").WithArguments("long?", "int?").WithLocation(10, 19), // (11,9): warning CS8629: Nullable value type may be null. // y2.Value.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2").WithLocation(11, 9), // (16,19): error CS0266: Cannot implicitly convert type 'long?' to 'int?'. An explicit conversion exists (are you missing a cast?) // int? y3 = x3; // 4 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x3").WithArguments("long?", "int?").WithLocation(16, 19) ); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ImplicitNullable_05() { var source = @"#pragma warning disable 0649 struct A { internal object? F; } struct B { internal object? F; } class Program { static void F1() { A a1 = new A(); B? b1 = a1; // 1 _ = b1.Value; b1.Value.F.ToString(); // 2 } static void F2() { A? a2 = new A() { F = 2 }; B? b2 = a2; // 3 _ = b2.Value; b2.Value.F.ToString(); // 4 } static void F3(A? a3) { B? b3 = a3; // 5 _ = b3.Value; // 6 b3.Value.F.ToString(); // 7 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,17): error CS0029: Cannot implicitly convert type 'A' to 'B?' // B? b1 = a1; // 1 Diagnostic(ErrorCode.ERR_NoImplicitConv, "a1").WithArguments("A", "B?").WithLocation(15, 17), // (17,9): warning CS8602: Dereference of a possibly null reference. // b1.Value.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b1.Value.F").WithLocation(17, 9), // (22,17): error CS0029: Cannot implicitly convert type 'A?' to 'B?' // B? b2 = a2; // 3 Diagnostic(ErrorCode.ERR_NoImplicitConv, "a2").WithArguments("A?", "B?").WithLocation(22, 17), // (24,9): warning CS8602: Dereference of a possibly null reference. // b2.Value.F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b2.Value.F").WithLocation(24, 9), // (28,17): error CS0029: Cannot implicitly convert type 'A?' to 'B?' // B? b3 = a3; // 5 Diagnostic(ErrorCode.ERR_NoImplicitConv, "a3").WithArguments("A?", "B?").WithLocation(28, 17), // (29,13): warning CS8629: Nullable value type may be null. // _ = b3.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b3").WithLocation(29, 13), // (30,9): warning CS8602: Dereference of a possibly null reference. // b3.Value.F.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b3.Value.F").WithLocation(30, 9) ); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ExplicitNullable_01() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { S x = new S() { F = 1, G = null }; // 1 var y = (S?)x; y.Value.F.ToString(); y.Value.G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // S x = new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 36), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.Value.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.G").WithLocation(13, 9)); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ExplicitNullable_02() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { S? x = new S() { F = 1, G = null }; // 1 S y = (S)x; y.F.ToString(); y.G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S? x = new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 37), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.G").WithLocation(13, 9)); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ExplicitNullable_03() { var source = @"class Program { static void F(int? x) { long? y = (long?)x; if (x == null) return; long? z = (long?)x; x.Value.ToString(); y.Value.ToString(); // 1 z.Value.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8629: Nullable value type may be null. // y.Value.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(9, 9) ); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ExplicitNullable_04() { var source = @"class Program { static void F(long? x) { int? y = (int?)x; if (x == null) return; int? z = (int?)x; x.Value.ToString(); y.Value.ToString(); // 1 z.Value.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8629: Nullable value type may be null. // y.Value.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(9, 9) ); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Conversions_ExplicitNullable_05() { var source = @"class Program { static void F1(int? x1) { int y1 = (int)x1; // 1 } static void F2(int? x2) { if (x2 == null) return; int y2 = (int)x2; } static void F3(int? x3) { long y3 = (long)x3; // 2 } static void F4(int? x4) { if (x4 == null) return; long y4 = (long)x4; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,18): warning CS8629: Nullable value type may be null. // int y1 = (int)x1; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int)x1").WithLocation(5, 18), // (14,19): warning CS8629: Nullable value type may be null. // long y3 = (long)x3; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(long)x3").WithLocation(14, 19)); } [Fact] [WorkItem(35334, "https://github.com/dotnet/roslyn/issues/35334")] public void Conversions_ExplicitNullable_UserDefinedIntroducingNullability() { var source = @" class A { public static explicit operator B(A a) => throw null!; } class B { void M(A a) { var b = ((B?)a)/*T:B?*/; b.ToString(); // 1 } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // b.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b").WithLocation(8, 9)); } [Fact] [WorkItem(32531, "https://github.com/dotnet/roslyn/issues/32531")] public void Tuple_Conversions_ImplicitNullable_01() { var source = @"struct S { internal object? F; } class Program { static void F() { S x = new S(); S y = new S() { F = 1 }; (S, S) t = (x, y); (S? x, S? y) u = t; (S?, S?) v = (x, y); t.Item1.F.ToString(); // 1 t.Item2.F.ToString(); u.x.Value.F.ToString(); // 2 u.y.Value.F.ToString(); v.Item1.Value.F.ToString(); // 3 v.Item2.Value.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.F").WithLocation(14, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // u.x.Value.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.x.Value.F").WithLocation(16, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // v.Item1.Value.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "v.Item1.Value.F").WithLocation(18, 9) ); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Tuple_Conversions_ImplicitNullable_02() { var source = @"struct S { internal object? F; } class Program { static void F() { S x = new S(); S y = new S() { F = 1 }; (S, S) t = (x, y); (S a, S b)? u = t; t.Item1.F.ToString(); // 1 t.Item2.F.ToString(); u.Value.a.F.ToString(); // 2 u.Value.b.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.F").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // u.Value.a.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Value.a.F").WithLocation(15, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Tuple_Conversions_ImplicitReference() { var source = @"class Program { static void F(string x, string? y) { (object?, string?) t = (x, y); (object? a, object? b) u = t; t.Item1.ToString(); t.Item2.ToString(); // 1 u.a.ToString(); u.b.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.b.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.b").WithLocation(10, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Tuple_Conversions_ImplicitDynamic() { var source = @"class Program { static void F(object x, object? y) { (object?, dynamic?) t = (x, y); (dynamic? a, object? b) u = t; t.Item1.ToString(); t.Item2.ToString(); // 1 u.a.ToString(); u.b.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.b.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.b").WithLocation(10, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Tuple_Conversions_Boxing() { var source = @"class Program { static void F(T x, U y, V? z) where U : struct where V : struct { (object, object, object) t = (x, y, z); // 1 t.Item1.ToString(); // 2 t.Item2.ToString(); t.Item3.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,38): warning CS8619: Nullability of reference types in value of type '(object? x, object y, object? z)' doesn't match target type '(object, object, object)'. // (object, object, object) t = (x, y, z); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y, z)").WithArguments("(object? x, object y, object? z)", "(object, object, object)").WithLocation(7, 38), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // t.Item3.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item3").WithLocation(10, 9)); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_Default_01() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F() where U : class where V : struct { default(S).F/*T:T*/.ToString(); // 1 default(S).F/*T:U?*/.ToString(); // 2 _ = default(S).F/*T:V?*/.Value; // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // default(S).F/*T:T*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(S).F").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // default(S).F/*T:U?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(S).F").WithLocation(13, 9), // (14,13): warning CS8629: Nullable value type may be null. // _ = default(S).F/*T:V?*/.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "default(S).F").WithLocation(14, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_Default_02() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F() where U : class where V : struct { new S().F/*T:T*/.ToString(); // 1 new S().F/*T:U?*/.ToString(); // 2 _ = new S().F/*T:V?*/.Value; // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // new S().F/*T:T*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new S().F").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // new S().F/*T:U?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new S().F").WithLocation(13, 9), // (14,13): warning CS8629: Nullable value type may be null. // _ = new S().F/*T:V?*/.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new S().F").WithLocation(14, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_Default_03() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F() { S x = default; S y = x; x.F/*T:object?*/.ToString(); // 1 y.F/*T:object?*/.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.F/*T:object?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(13, 9)); comp.VerifyTypes(); } [Fact] public void StructField_Default_04() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F() { S x = default; S y = x; _ = x.F.Value; // 1 _ = y.F.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8629: Nullable value type may be null. // _ = x.F.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F").WithLocation(12, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = y.F.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.F").WithLocation(13, 13) ); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_Default_05() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F() { var x = new S(); var y = x; x.F/*T:object?*/.ToString(); // 1 y.F/*T:object?*/.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.F/*T:object?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(13, 9)); comp.VerifyTypes(); } [Fact] public void StructField_Default_06() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F() { var x = new S(); var y = x; _ = x.F.Value; // 1 _ = y.F.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8629: Nullable value type may be null. // _ = x.F.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F").WithLocation(12, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = y.F.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.F").WithLocation(13, 13) ); } [Fact] public void StructField_Default_07() { var source = @"#pragma warning disable 649 struct S { internal T F; internal U G; } class Program { static void F(object a, string b) { var x = new S() { F = a }; x.F/*T:object!*/.ToString(); x.G/*T:string?*/.ToString(); // 1 var y = new S() { G = b }; y.F/*T:object?*/.ToString(); // 2 y.G/*T:string!*/.ToString(); var z = new S() { F = default, G = default }; // 3, 4 z.F/*T:object?*/.ToString(); // 5 z.G/*T:string?*/.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // x.G/*T:string?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.G").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.F/*T:object?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(15, 9), // (17,47): warning CS8625: Cannot convert null literal to non-nullable reference type. // var z = new S() { F = default, G = default }; // 3, 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(17, 47), // (17,60): warning CS8625: Cannot convert null literal to non-nullable reference type. // var z = new S() { F = default, G = default }; // 3, 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(17, 60), // (18,9): warning CS8602: Dereference of a possibly null reference. // z.F/*T:object?*/.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.F").WithLocation(18, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // z.G/*T:string?*/.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.G").WithLocation(19, 9)); comp.VerifyTypes(); } [Fact] public void StructField_Default_ParameterlessConstructor() { var source = @"#pragma warning disable 649 struct S { internal T F; internal S() { F = default!; } internal S(T t) { F = t; } } class Program { static void F() { var x = default(S); x.F/*T:object?*/.ToString(); // 1 var y = new S(); y.F/*T:object!*/.ToString(); var z = new S(1); z.F/*T:object!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,14): error CS0568: Structs cannot contain explicit parameterless constructors // internal S() { F = default!; } Diagnostic(ErrorCode.ERR_StructsCantContainDefaultConstructor, "S").WithLocation(5, 14), // (13,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(13, 9)); comp.VerifyTypes(); } [Fact] public void StructField_Default_NoType() { var source = @"class Program { static void F() { _ = default/*T:?*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,33): error CS0023: Operator '.' cannot be applied to operand of type 'default' // _ = default/*T:?*/.ToString(); Diagnostic(ErrorCode.ERR_BadUnaryOp, ".").WithArguments(".", "default").WithLocation(5, 33)); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_ParameterDefaultValue_01() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F1(S x1 = default) { var y1 = x1; x1.F/*T:T1*/.ToString(); // 1 y1.F/*T:T1*/.ToString(); // 2 } static void F2(S x2 = default) where T2 : class { var y2 = x2; x2.F/*T:T2?*/.ToString(); // 3 y2.F/*T:T2?*/.ToString(); // 4 } static void F3(S x3 = default) where T3 : struct { var y3 = x3; _ = x3.F/*T:T3?*/.Value; // 5 _ = y3.F/*T:T3?*/.Value; // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // x1.F/*T:T1*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1.F").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // y1.F/*T:T1*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1.F").WithLocation(12, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // x2.F/*T:T2?*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2.F").WithLocation(17, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // y2.F/*T:T2?*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2.F").WithLocation(18, 9), // (23,13): warning CS8629: Nullable value type may be null. // _ = x3.F/*T:T3?*/.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3.F").WithLocation(23, 13), // (24,13): warning CS8629: Nullable value type may be null. // _ = y3.F/*T:T3?*/.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3.F").WithLocation(24, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_ParameterDefaultValue_02() { var source = @"#pragma warning disable 649 struct S { internal T F; internal S(T t) { F = t; } } class Program { static void F(S x = new S(), S y = null, S z = new S(default)) where T : class { x.F/*T:T?*/.ToString(); // 1 y.F/*T:T!*/.ToString(); z.F/*T:T!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,48): error CS1750: A value of type '' cannot be used as a default parameter because there are no standard conversions to type 'S' // static void F(S x = new S(), S y = null, S z = new S(default)) where T : class Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "y").WithArguments("", "S").WithLocation(9, 48), // (9,67): error CS1736: Default parameter value for 'z' must be a compile-time constant // static void F(S x = new S(), S y = null, S z = new S(default)) where T : class Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "new S(default)").WithArguments("z").WithLocation(9, 67), // (11,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:T?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(11, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_ParameterDefaultValue_03() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F(S x = /*missing*/, S y = default) where T : class { x.F/*T:T!*/.ToString(); y.F/*T:T?*/.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,42): error CS1525: Invalid expression term ',' // static void F(S x = /*missing*/, S y = default) where T : class Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(8, 42), // (11,9): warning CS8602: Dereference of a possibly null reference. // y.F/*T:T?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(11, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_ParameterDefaultValue_04() { var source = @"#pragma warning disable 649 struct S { internal T F; } class Program { static void F(S? x = default(S)) where T : class { if (x == null) return; var y = x.Value; y.F/*T:T!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,28): error CS1770: A value of type 'S' cannot be used as default parameter for nullable parameter 'x' because 'S' is not a simple type // static void F(S? x = default(S)) where T : class Diagnostic(ErrorCode.ERR_NoConversionForNubDefaultParam, "x").WithArguments("S", "x").WithLocation(8, 28)); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void StructField_Default_Nested() { var source = @"#pragma warning disable 649 struct S { internal S(int i) { S1 = null!; T = default; } internal object S1; internal T T; } struct T { internal object T1; } class Program { static void F1() { // default S s1 = default; s1.S1.ToString(); // 1 s1.T.T1.ToString(); // 2 } static void F2() { // default constructor S s2 = new S(); s2.S1.ToString(); // 3 s2.T.T1.ToString(); // 4 } static void F3() { // explicit constructor S s3 = new S(0); s3.S1.ToString(); s3.T.T1.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (22,9): warning CS8602: Dereference of a possibly null reference. // s1.S1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1.S1").WithLocation(22, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // s1.T.T1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1.T.T1").WithLocation(23, 9), // (29,9): warning CS8602: Dereference of a possibly null reference. // s2.S1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2.S1").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // s2.T.T1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2.T.T1").WithLocation(30, 9)); } [Fact] public void StructField_Cycle_Default() { // Nullability of F is treated as object!, even for default instances, because a struct with cycles // is not a "trackable" struct type (see EmptyStructTypeCache.IsTrackableStructType). var source = @"#pragma warning disable 649 struct S { internal S Next; internal object F; } class Program { static void F() { default(S).F/*T:object!*/.ToString(); S x = default; S y = x; x.F/*T:object!*/.ToString(); x.Next.F/*T:object!*/.ToString(); y.F/*T:object!*/.ToString(); y.Next.F/*T:object!*/.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,16): error CS0523: Struct member 'S.Next' of type 'S' causes a cycle in the struct layout // internal S Next; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "Next").WithArguments("S.Next", "S").WithLocation(4, 16)); comp.VerifyTypes(); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructProperty_Cycle_Default() { var source = @"#pragma warning disable 649 struct S { internal S Next { get => throw null!; set { } } internal object F; } class Program { static void F() { S x = default; S y = x; x.F/*T:object?*/.ToString(); // 1 x.Next.F/*T:object!*/.ToString(); y.F/*T:object?*/.ToString(); // 2 y.Next.F/*T:object!*/.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(17, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // y.F/*T:object?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(19, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructProperty_Cycle() { var source = @"struct S { internal object? F; internal S P { get { return this; } set { this = value; } } } class Program { static void M(S s) { s.F = 2; for (int i = 0; i < 3; i++) { s.P = s; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructField_Cycle_01() { var source = @"#pragma warning disable 649 struct S { internal S F; internal object? P => null; } class Program { static void F(S x, S y) { if (y.P == null) return; x.P.ToString(); // 1 y.P.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,16): error CS0523: Struct member 'S.F' of type 'S' causes a cycle in the struct layout // internal S F; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "F").WithArguments("S.F", "S").WithLocation(4, 16), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.P").WithLocation(12, 9)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructField_Cycle_02() { var source0 = @".class public sealed S extends [mscorlib]System.ValueType { .field public valuetype [mscorlib]System.Nullable`1 F }"; var ref0 = CompileIL(source0); var source = @"class Program { static void F(S x, S y) { if (y.F == null) return; _ = x.F.Value; // 1 _ = y.F.Value; } }"; var comp = CreateCompilation(new[] { source }, new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = x.F.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.F").WithLocation(6, 13)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructField_Cycle_03() { var source0 = @".class public sealed S extends [mscorlib]System.ValueType { .field public valuetype S F .field public object G }"; var ref0 = CompileIL(source0); var source = @"class Program { static void F(S s) { s.G = null; s.G.ToString(); // 1 } }"; var comp = CreateCompilation(new[] { source }, new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s.G.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.G").WithLocation(6, 9)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructField_Cycle_04() { var source0 = @".class public sealed S extends [mscorlib]System.ValueType { .field public valuetype S F .method public instance object get_P() { ldnull ret } .method public instance void set_P(object 'value') { ret } .property instance object P() { .get instance object S::get_P() .set instance void S::set_P(object) } }"; var ref0 = CompileIL(source0); var source = @"class Program { static void F(S s) { s.P = null; s.P.ToString(); // 1 } }"; var comp = CreateCompilation(new[] { source }, new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void StructPropertyNoBackingField() { var source0 = @".class public sealed S extends [mscorlib]System.ValueType { .method public instance object get_P() { ldnull ret } .method public instance void set_P(object 'value') { ret } .property instance object P() { .get instance object S::get_P() .set instance void S::set_P(object) } }"; var ref0 = CompileIL(source0); var source = @"class Program { static void F(S s) { s.P = null; s.P.ToString(); // 1 } }"; var comp = CreateCompilation(new[] { source }, new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // s.P.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.P").WithLocation(6, 9)); } // `default` expression in a split state. [Fact] public void IsPattern_DefaultTrackableStruct() { var source = @"#pragma warning disable 649 struct S { internal object F; } class Program { static void F() { if (default(S) is default) { } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,27): error CS8505: A default literal 'default' is not valid as a pattern. Use another literal (e.g. '0' or 'null') as appropriate. To match everything, use a discard pattern '_'. // if (default(S) is default) { } Diagnostic(ErrorCode.ERR_DefaultPattern, "default").WithLocation(10, 27), // (10,27): error CS0150: A constant value is expected // if (default(S) is default) { } Diagnostic(ErrorCode.ERR_ConstantExpected, "default").WithLocation(10, 27)); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_Default_01() { var source = @"class Program { static void F() { default((object?, string))/*T:(object?, string!)*/.Item2.ToString(); // 1 _ = default((int, int?))/*T:(int, int?)*/.Item2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // default((object?, string))/*T:(object?, string!)*/.Item2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default((object?, string))/*T:(object?, string!)*/.Item2").WithLocation(5, 9), // (6,13): warning CS8629: Nullable value type may be null. // _ = default((int, int?))/*T:(int, int?)*/.Item2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "default((int, int?))/*T:(int, int?)*/.Item2").WithLocation(6, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_Default_02() { var source = @"using System; class Program { static void F1() { new ValueTuple()/*T:(object?, string!)*/.Item2.ToString(); // 1 _ = new ValueTuple()/*T:(int, int?)*/.Item2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // new ValueTuple()/*T:(object?, string!)*/.Item2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "new ValueTuple()/*T:(object?, string!)*/.Item2").WithLocation(6, 9), // (7,13): warning CS8629: Nullable value type may be null. // _ = new ValueTuple()/*T:(int, int?)*/.Item2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "new ValueTuple()/*T:(int, int?)*/.Item2").WithLocation(7, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_Default_03() { var source = @"class Program { static void F() { (object, (object?, string)) t = default/*T:(object!, (object?, string!))*/; (object, (object?, string)) u = t; t.Item1/*T:object?*/.ToString(); // 1 t.Item2.Item2/*T:string?*/.ToString(); // 2 u.Item1/*T:object?*/.ToString(); // 3 u.Item2.Item2/*T:string?*/.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // t.Item1/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.Item2/*T:string?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2.Item2").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // u.Item1/*T:object?*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.Item2/*T:string?*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2.Item2").WithLocation(10, 9)); comp.VerifyTypes(); } [Fact] public void Tuple_Default_04() { var source = @"class Program { static void F() { (int, int?) t = default/*T:(int, int?)*/; (int, int?) u = t; _ = t.Item2.Value; // 1 _ = u.Item2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(7, 13), // (8,13): warning CS8629: Nullable value type may be null. // _ = u.Item2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.Item2").WithLocation(8, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_Default_05() { var source = @"using System; class Program { static void F1() { var t = new ValueTuple>()/*T:(object!, (object?, string!))*/; var u = t; t.Item1/*T:object?*/.ToString(); // 1 t.Item2.Item2/*T:string?*/.ToString(); // 2 u.Item1/*T:object?*/.ToString(); // 3 u.Item2.Item2/*T:string?*/.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.Item1/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.Item2/*T:string?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2.Item2").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.Item1/*T:object?*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item1").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.Item2/*T:string?*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2.Item2").WithLocation(11, 9)); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_Default_06() { var source = @"using System; class Program { static void F1() { var t = new ValueTuple()/*T:(int, int?)*/; var u = t; _ = t.Item2.Value; // 1 _ = u.Item2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(8, 13), // (9,13): warning CS8629: Nullable value type may be null. // _ = u.Item2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.Item2").WithLocation(9, 13) ); comp.VerifyTypes(); } [Fact] public void Tuple_Default_NoType() { var source = @"class Program { static void F(object? x) { _ = (default, default)/*T:!*/.Item1.ToString(); _ = (x, default)/*T:!*/.Item2.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,45): error CS0117: '(default, default)' does not contain a definition for 'Item1' // _ = (default, default)/*T:!*/.Item1.ToString(); Diagnostic(ErrorCode.ERR_NoSuchMember, "Item1").WithArguments("(default, default)", "Item1").WithLocation(5, 45), // (6,39): error CS0117: '(object, default)' does not contain a definition for 'Item2' // _ = (x, default)/*T:!*/.Item2.ToString(); Diagnostic(ErrorCode.ERR_NoSuchMember, "Item2").WithArguments("(object, default)", "Item2").WithLocation(6, 39)); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_ParameterDefaultValue_01() { var source = @"class Program { static void F((T x, U y, V? z) t = default) where U : class where V : struct { var u = t/*T:(T x, U! y, V? z)*/; t.x/*T:T*/.ToString(); // 1 t.y/*T:U?*/.ToString(); // 2 _ = t.z/*T:V?*/.Value; // 3 u.x/*T:T*/.ToString(); // 4 u.y/*T:U?*/.ToString(); // 5 _ = u.z/*T:V?*/.Value; // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.x/*T:T*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.x").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.y/*T:U?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(9, 9), // (10,13): warning CS8629: Nullable value type may be null. // _ = t.z/*T:V?*/.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.z").WithLocation(10, 13), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.x/*T:T*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.x").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // u.y/*T:U?*/.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(12, 9), // (13,13): warning CS8629: Nullable value type may be null. // _ = u.z/*T:V?*/.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u.z").WithLocation(13, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(30731, "https://github.com/dotnet/roslyn/issues/30731")] public void Tuple_ParameterDefaultValue_02() { var source = @"class Program { static void F( (T, U, V?) x = new System.ValueTuple(), (T, U, V?) y = null, (T, U, V?) z = (default(T), new U(), new V())) where U : class, new() where V : struct { x.Item1/*T:T*/.ToString(); // 1 x.Item2/*T:U?*/.ToString(); // 2 _ = x.Item3/*T:V?*/.Value; // 3 y.Item1/*T:T*/.ToString(); // 4 y.Item2/*T:U!*/.ToString(); _ = y.Item3/*T:V?*/.Value; // 5 z.Item1/*T:T*/.ToString(); // 6 z.Item2/*T:U!*/.ToString(); _ = z.Item3/*T:V?*/.Value; // 7 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): error CS1750: A value of type '' cannot be used as a default parameter because there are no standard conversions to type '(T, U, V?)' // (T, U, V?) y = null, Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "y").WithArguments("", "(T, U, V?)").WithLocation(5, 20), // (6,24): error CS1736: Default parameter value for 'z' must be a compile-time constant // (T, U, V?) z = (default(T), new U(), new V())) Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "(default(T), new U(), new V())").WithArguments("z").WithLocation(6, 24), // (10,9): warning CS8602: Dereference of a possibly null reference. // x.Item1/*T:T*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item1").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // x.Item2/*T:U?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item2").WithLocation(11, 9), // (12,13): warning CS8629: Nullable value type may be null. // _ = x.Item3/*T:V?*/.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x.Item3").WithLocation(12, 13), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.Item1/*T:T*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(13, 9), // (15,13): warning CS8629: Nullable value type may be null. // _ = y.Item3/*T:V?*/.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y.Item3").WithLocation(15, 13), // (16,9): warning CS8602: Dereference of a possibly null reference. // z.Item1/*T:T*/.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Item1").WithLocation(16, 9), // (18,13): warning CS8629: Nullable value type may be null. // _ = z.Item3/*T:V?*/.Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z.Item3").WithLocation(18, 13) ); comp.VerifyTypes(); } [Fact] public void Tuple_Constructor() { var source = @"class C { C((string x, string? y) t) { } static void M(string x, string? y) { C c; c = new C((x, x)); c = new C((x, y)); c = new C((y, x)); // 1 c = new C((y, y)); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,19): warning CS8620: Nullability of reference types in argument of type '(string? y, string x)' doesn't match target type '(string x, string? y)' for parameter 't' in 'C.C((string x, string? y) t)'. // c = new C((y, x)); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, x)").WithArguments("(string? y, string x)", "(string x, string? y)", "t", "C.C((string x, string? y) t)").WithLocation(9, 19), // (10,19): warning CS8620: Nullability of reference types in argument of type '(string?, string?)' doesn't match target type '(string x, string? y)' for parameter 't' in 'C.C((string x, string? y) t)'. // c = new C((y, y)); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, y)").WithArguments("(string?, string?)", "(string x, string? y)", "t", "C.C((string x, string? y) t)").WithLocation(10, 19)); } [Fact] public void Tuple_Indexer() { var source = @"class C { object? this[(string x, string? y) t] => null; static void M(string x, string? y) { var c = new C(); object? o; o = c[(x, x)]; o = c[(x, y)]; o = c[(y, x)]; // 1 o = c[(y, y)]; // 2 var t = (y, x); o = c[t]; // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,15): warning CS8620: Nullability of reference types in argument of type '(string? y, string x)' doesn't match target type '(string x, string? y)' for parameter 't' in 'object? C.this[(string x, string? y) t]'. // o = c[(y, x)]; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, x)").WithArguments("(string? y, string x)", "(string x, string? y)", "t", "object? C.this[(string x, string? y) t]").WithLocation(10, 15), // (11,15): warning CS8620: Nullability of reference types in argument of type '(string?, string?)' doesn't match target type '(string x, string? y)' for parameter 't' in 'object? C.this[(string x, string? y) t]'. // o = c[(y, y)]; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, y)").WithArguments("(string?, string?)", "(string x, string? y)", "t", "object? C.this[(string x, string? y) t]").WithLocation(11, 15), // (13,15): warning CS8620: Nullability of reference types in argument of type '(string? y, string x)' doesn't match target type '(string x, string? y)' for parameter 't' in 'object? C.this[(string x, string? y) t]'. // o = c[t]; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "t").WithArguments("(string? y, string x)", "(string x, string? y)", "t", "object? C.this[(string x, string? y) t]").WithLocation(13, 15)); } [Fact] public void Tuple_CollectionInitializer() { var source = @"using System.Collections.Generic; class C { static void M(string x, string? y) { var c = new List<(string, string?)> { (x, x), (x, y), (y, x), // 1 (y, y), // 2 }; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8620: Nullability of reference types in argument of type '(string? y, string x)' doesn't match target type '(string, string?)' for parameter 'item' in 'void List<(string, string?)>.Add((string, string?) item)'. // (y, x), // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, x)").WithArguments("(string? y, string x)", "(string, string?)", "item", "void List<(string, string?)>.Add((string, string?) item)").WithLocation(10, 13), // (11,13): warning CS8620: Nullability of reference types in argument of type '(string?, string?)' doesn't match target type '(string, string?)' for parameter 'item' in 'void List<(string, string?)>.Add((string, string?) item)'. // (y, y), // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "(y, y)").WithArguments("(string?, string?)", "(string, string?)", "item", "void List<(string, string?)>.Add((string, string?) item)").WithLocation(11, 13)); } [Fact] public void Tuple_Method() { var source = @"class C { static void F(object? x, object? y) { if (x == null) return; (x, y).ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Tuple_OtherMembers_01() { var source = @"internal delegate T D(); namespace System { public struct ValueTuple { public ValueTuple(T1 item1, T2 item2) { Item1 = item1; Item2 = item2; F1 = item1; E2 = null; } public T1 Item1; public T2 Item2; internal T1 F1; internal T1 P1 => Item1; internal event D? E2; } } class C { static void F(object? x) { var y = (x, x); y.F1.ToString(); // 1 y.P1.ToString(); // 2 y.E2?.Invoke().ToString(); // 3 if (x == null) return; var z = (x, x); z.F1.ToString(); z.P1.ToString(); z.E2?.Invoke().ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), targetFramework: TargetFramework.Mscorlib46); comp.VerifyDiagnostics( // (27,11): error CS0070: The event '(object, object).E2' can only appear on the left hand side of += or -= (except when used from within the type '(object, object)') // y.E2?.Invoke().ToString(); // 3 Diagnostic(ErrorCode.ERR_BadEventUsage, "E2").WithArguments("(object, object).E2", "(object, object)").WithLocation(27, 11), // (32,11): error CS0070: The event '(object, object).E2' can only appear on the left hand side of += or -= (except when used from within the type '(object, object)') // z.E2?.Invoke().ToString(); Diagnostic(ErrorCode.ERR_BadEventUsage, "E2").WithArguments("(object, object).E2", "(object, object)").WithLocation(32, 11), // (25,9): warning CS8602: Dereference of a possibly null reference. // y.F1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F1").WithLocation(25, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // y.P1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.P1").WithLocation(26, 9), // (17,31): warning CS0414: The field 'ValueTuple.E2' is assigned but its value is never used // internal event D? E2; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "E2").WithArguments("System.ValueTuple.E2").WithLocation(17, 31)); } [Fact] public void Tuple_OtherMembers_02() { // https://github.com/dotnet/roslyn/issues/33578 // Cannot test Derived since tuple types are considered sealed and the base type // is dropped: "error CS0509: 'Derived': cannot derive from sealed type '(T, T)'". var source = @"namespace System { public class Base { public Base(T t) { F = t; } public T F; } public class ValueTuple : Base { public ValueTuple(T1 item1, T2 item2) : base(item1) { Item1 = item1; Item2 = item2; } public T1 Item1; public T2 Item2; } //public class Derived : ValueTuple //{ // public Derived(T t) : base(t, t) { } // public T P { get; set; } //} } class C { static void F(object? x) { var y = (x, x); y.F.ToString(); // 1 y.Item2.ToString(); // 2 if (x == null) return; var z = (x, x); z.F.ToString(); z.Item2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), targetFramework: TargetFramework.Mscorlib46); comp.VerifyDiagnostics( // (29,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. // y.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item2").WithLocation(30, 9)); } [Fact] public void Tuple_OtherMembers_03() { var source = @"namespace System { public class Object { public string ToString() => throw null!; public object? F; } public class String { } public abstract class ValueType { public object? P { get; set; } } public struct Void { } public struct Boolean { } public struct Enum { } public class Attribute { } public struct Int32 { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } public struct ValueTuple { public ValueTuple(T1 item1, T2 item2) { } } } class C { static void M(object x) { var y = (x, x); y.F.ToString(); y.P.ToString(); } }"; var comp = CreateEmptyCompilation(source); comp.VerifyDiagnostics( // (6,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public object? F; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 22), // (11,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public object? P { get; set; } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 22) ); var comp2 = CreateEmptyCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp2.VerifyDiagnostics( // (44,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(44, 9), // (45,9): warning CS8602: Dereference of a possibly null reference. // y.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.P").WithLocation(45, 9)); } [Fact] public void TypeInference_TupleNameDifferences_01() { var source = @"class C { } static class E { public static T F(this C c, T t) => t; } class C { static void F(object o) { var c = new C<(object x, int y)>(); c.F((o, -1)).x.ToString(); } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics( // (13,22): error CS1061: '(object, int)' does not contain a definition for 'x' and no extension method 'x' accepting a first argument of type '(object, int)' could be found (are you missing a using directive or an assembly reference?) // c.F((o, -1)).x.ToString(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("(object, int)", "x").WithLocation(13, 22)); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,22): error CS1061: '(object, int)' does not contain a definition for 'x' and no extension method 'x' accepting a first argument of type '(object, int)' could be found (are you missing a using directive or an assembly reference?) // c.F((o, -1)).x.ToString(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("(object, int)", "x").WithLocation(13, 22)); } [Fact] public void TypeInference_TupleNameDifferences_02() { var source = @"class C { } static class E { public static T F(this C c, T t) => t; } class C { static void F(object o) { var c = new C<(object? x, int y)>(); c.F((o, -1))/*T:(object?, int)*/.x.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,42): error CS1061: '(object, int)' does not contain a definition for 'x' and no accessible extension method 'x' accepting a first argument of type '(object, int)' could be found (are you missing a using directive or an assembly reference?) // c.F((o, -1))/*T:(object?, int)*/.x.ToString(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("(object, int)", "x").WithLocation(13, 42)); comp.VerifyTypes(); } [Fact] public void TypeInference_DynamicDifferences_01() { var source = @"class C { } static class E { public static T F(this C c, T t) => t; } class C { static void F(dynamic x, object y) { var c = new C<(object, object)>(); c.F((x, y))/*T:(dynamic!, object!)*/.Item1.G(); } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void TypeInference_DynamicDifferences_02() { var source = @"class C { } static class E { public static T F(this C c, T t) => t; } class C { static void F(dynamic x, object y) { var c = new C<(object, object?)>(); c.F((x, y))/*T:(dynamic!, object?)*/.Item1.G(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } // Assert failure in ConversionsBase.IsValidExtensionMethodThisArgConversion. [WorkItem(22317, "https://github.com/dotnet/roslyn/issues/22317")] [Fact(Skip = "22317")] public void TypeInference_DynamicDifferences_03() { var source = @"interface I { } static class E { public static T F(this I i, T t) => t; } class C { static void F(I i, dynamic? d) { i.F(d).G(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): error CS1929: 'I' does not contain a definition for 'F' and the best extension method overload 'E.F(I, T)' requires a receiver of type 'I' // i.F(d).G(); Diagnostic(ErrorCode.ERR_BadInstanceArgType, "i").WithArguments("I", "F", "E.F(I, T)", "I").WithLocation(12, 9)); } [Fact] public void NullableConversionAndNullCoalescingOperator_01() { var source = @"#pragma warning disable 0649 struct S { short F; static ushort G(S? s) { return (ushort)(s?.F ?? 0); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableConversionAndNullCoalescingOperator_02() { var source = @"struct S { public static implicit operator int(S s) => 0; } class P { static int F(S? x, int y) => x ?? y; static int G(S x, int? y) => y ?? x; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ConstrainedToTypeParameter_01() { var source = @"class C where U : T { }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ConstrainedToTypeParameter_02() { var source = @"class C where T : C { }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ArrayElementConversion() { var source = @"class C { static object F() => new sbyte[] { -1 }; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void TrackNonNullableLocals() { var source = @"class C { static void F(object x) { object y = x; x.ToString(); // 1 y.ToString(); // 2 x = null; y = x; x.ToString(); // 3 y.ToString(); // 4 x = null; y = x; if (x == null) return; if (y == null) return; x.ToString(); // 5 y.ToString(); // 6 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(8, 13), // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(11, 9), // (12,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 13), // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(13, 13)); } [Fact] public void TrackNonNullableFieldsAndProperties() { var source = @"#pragma warning disable 8618 class C { object F; object P { get; set; } static void M(C c) { c.F.ToString(); // 1 c.P.ToString(); // 2 c.F = null; c.P = null; c.F.ToString(); // 3 c.P.ToString(); // 4 if (c.F == null) return; if (c.P == null) return; c.F.ToString(); // 5 c.P.ToString(); // 6 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.F = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 15), // (11,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.P = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 15), // (12,9): warning CS8602: Dereference of a possibly null reference. // c.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // c.P.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(13, 9)); } [Fact] public void TrackNonNullableFields_ObjectInitializer() { var source = @"class C { internal T F = default!; } class Program { static void F1(object? x1) { C c1; c1 = new C() { F = x1 }; // 1 c1 = new C() { F = c1.F }; // 2 c1.F.ToString(); // 3 } static void F2() { C c2; c2 = new C() { F = default }; // 4 c2 = new C() { F = c2.F }; c2.F.ToString(); // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,36): warning CS8601: Possible null reference assignment. // c1 = new C() { F = x1 }; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x1").WithLocation(10, 36), // (11,36): warning CS8601: Possible null reference assignment. // c1 = new C() { F = c1.F }; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c1.F").WithLocation(11, 36), // (12,9): warning CS8602: Dereference of a possibly null reference. // c1.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(12, 9), // (17,31): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // c2 = new C() { F = default }; // 4 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(17, 31), // (19,9): warning CS8602: Dereference of a possibly null reference. // c2.F.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2.F").WithLocation(19, 9)); } [Fact] public void TrackUnannotatedFieldsAndProperties() { var source0 = @"public class C { public object F; public object P { get; set; } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var source1 = @"class P { static void M(C c, object? o) { c.F.ToString(); c.P.ToString(); c.F = o; c.P = o; c.F.ToString(); // 1 c.P.ToString(); // 2 c.F = o; c.P = o; if (c.F == null) return; if (c.P == null) return; c.F.ToString(); c.P.ToString(); } }"; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { comp0.EmitToImageReference() }); comp1.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // c.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // c.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.P").WithLocation(10, 9)); } /// /// Assignment warnings for local and parameters should be distinct from /// fields and properties because the former may be warnings from legacy /// method bodies and it should be possible to disable those warnings separately. /// [Fact] public void AssignmentWarningsDistinctForLocalsAndParameters() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { internal object F; internal object P { get; set; } } class P { static void F(out object? x) { x = null; } static void Local() { object? y = null; object x1 = null; x1 = y; F(out x1); } static void Parameter(object x2) { object? y = null; x2 = null; x2 = y; F(out x2); } static void OutParameter(out object x3) { object? y = null; x3 = null; x3 = y; F(out x3); } static void RefParameter(ref object x4) { object? y = null; x4 = null; x4 = y; F(out x4); } static void Field() { var c = new C(); object? y = null; c.F = null; c.F = y; F(out c.F); } static void Property() { var c = new C(); object? y = null; c.P = null; c.P = y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object x1 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(17, 21), // (18,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = y; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(18, 14), // (19,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(out x1); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x1").WithLocation(19, 15), // (24,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(24, 14), // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = y; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(25, 14), // (26,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // F(out x2); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(26, 15), // (31,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // x3 = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(31, 14), // (32,14): warning CS8601: Possible null reference assignment. // x3 = y; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(32, 14), // (33,15): warning CS8601: Possible null reference assignment. // F(out x3); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x3").WithLocation(33, 15), // (38,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // x4 = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(38, 14), // (39,14): warning CS8601: Possible null reference assignment. // x4 = y; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(39, 14), // (40,15): warning CS8601: Possible null reference assignment. // F(out x4); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x4").WithLocation(40, 15), // (46,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.F = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(46, 15), // (47,15): warning CS8601: Possible null reference assignment. // c.F = y; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(47, 15), // (48,15): warning CS8601: Possible null reference assignment. // F(out c.F); Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c.F").WithLocation(48, 15), // (54,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.P = null; Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(54, 15), // (55,15): warning CS8601: Possible null reference assignment. // c.P = y; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(55, 15)); } /// /// Explicit cast does not cast away top-level nullability. /// [Fact] public void ExplicitCast() { var source = @"#pragma warning disable 0649 class A { internal T F; } class B1 : A { } class B2 : A { } class C { static void F0() { ((A)null).F.ToString(); ((A?)null).F.ToString(); ((A)default).F.ToString(); ((A?)default).F.ToString(); } static void F1(A x1, A? y1) { ((B2?)x1).F.ToString(); ((B2)y1).F.ToString(); } static void F2(B1 x2, B1? y2) { ((A?)x2).F.ToString(); ((A)y2).F.ToString(); } static void F3(A x3, A? y3) { ((B2?)x3).F.ToString(); ((B2)y3).F.ToString(); } static void F4(B2 x4, B2? y4) { ((A?)x4).F.ToString(); ((A)y4).F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,16): warning CS8618: Non-nullable field 'F' is uninitialized. // internal T F; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(4, 16), // (12,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((A)null).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)null").WithLocation(12, 10), // (12,10): warning CS8602: Dereference of a possibly null reference. // ((A)null).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A)null").WithLocation(12, 10), // (13,10): warning CS8602: Dereference of a possibly null reference. // ((A?)null).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A?)null").WithLocation(13, 10), // (14,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((A)default).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)default").WithLocation(14, 10), // (14,10): warning CS8602: Dereference of a possibly null reference. // ((A)default).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A)default").WithLocation(14, 10), // (14,9): warning CS8602: Dereference of a possibly null reference. // ((A)default).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A)default).F").WithLocation(14, 9), // (15,10): warning CS8602: Dereference of a possibly null reference. // ((A?)default).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A?)default").WithLocation(15, 10), // (15,9): warning CS8602: Dereference of a possibly null reference. // ((A?)default).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A?)default).F").WithLocation(15, 9), // (19,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B2'. // ((B2?)x1).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B2?)x1").WithArguments("A", "B2").WithLocation(19, 10), // (19,10): warning CS8602: Dereference of a possibly null reference. // ((B2?)x1).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(B2?)x1").WithLocation(19, 10), // (19,9): warning CS8602: Dereference of a possibly null reference. // ((B2?)x1).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B2?)x1).F").WithLocation(19, 9), // (20,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((B2)y1).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B2)y1").WithLocation(20, 10), // (20,10): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B2'. // ((B2)y1).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B2)y1").WithArguments("A", "B2").WithLocation(20, 10), // (20,10): warning CS8602: Dereference of a possibly null reference. // ((B2)y1).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(B2)y1").WithLocation(20, 10), // (20,9): warning CS8602: Dereference of a possibly null reference. // ((B2)y1).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B2)y1).F").WithLocation(20, 9), // (24,10): warning CS8619: Nullability of reference types in value of type 'B1' doesn't match target type 'A'. // ((A?)x2).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A?)x2").WithArguments("B1", "A").WithLocation(24, 10), // (24,10): warning CS8602: Dereference of a possibly null reference. // ((A?)x2).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A?)x2").WithLocation(24, 10), // (24,9): warning CS8602: Dereference of a possibly null reference. // ((A?)x2).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A?)x2).F").WithLocation(24, 9), // (25,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((A)y2).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)y2").WithLocation(25, 10), // (25,10): warning CS8619: Nullability of reference types in value of type 'B1' doesn't match target type 'A'. // ((A)y2).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)y2").WithArguments("B1", "A").WithLocation(25, 10), // (25,10): warning CS8602: Dereference of a possibly null reference. // ((A)y2).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A)y2").WithLocation(25, 10), // (25,9): warning CS8602: Dereference of a possibly null reference. // ((A)y2).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((A)y2).F").WithLocation(25, 9), // (29,10): warning CS8602: Dereference of a possibly null reference. // ((B2?)x3).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(B2?)x3").WithLocation(29, 10), // (29,9): warning CS8602: Dereference of a possibly null reference. // ((B2?)x3).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B2?)x3).F").WithLocation(29, 9), // (30,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((B2)y3).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B2)y3").WithLocation(30, 10), // (30,10): warning CS8602: Dereference of a possibly null reference. // ((B2)y3).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(B2)y3").WithLocation(30, 10), // (30,9): warning CS8602: Dereference of a possibly null reference. // ((B2)y3).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B2)y3).F").WithLocation(30, 9), // (34,10): warning CS8619: Nullability of reference types in value of type 'B2' doesn't match target type 'A'. // ((A?)x4).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A?)x4").WithArguments("B2", "A").WithLocation(34, 10), // (34,10): warning CS8602: Dereference of a possibly null reference. // ((A?)x4).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A?)x4").WithLocation(34, 10), // (35,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((A)y4).F.ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(A)y4").WithLocation(35, 10), // (35,10): warning CS8619: Nullability of reference types in value of type 'B2' doesn't match target type 'A'. // ((A)y4).F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)y4").WithArguments("B2", "A").WithLocation(35, 10), // (35,10): warning CS8602: Dereference of a possibly null reference. // ((A)y4).F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(A)y4").WithLocation(35, 10) ); } [Fact] public void ExplicitCast_NestedNullability_01() { var source = @"class A { } class B : A { } class C { static void F1(A x1, A y1) { object o; o = (B)x1; o = (B)x1; // 1 o = (B)y1; // 2 o = (B)y1; } static void F2(B x2, B y2) { object o; o = (A)x2; o = (A)x2; // 3 o = (A)y2; // 4 o = (A)y2; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // o = (B)x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)x1").WithArguments("A", "B").WithLocation(9, 13), // (10,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // o = (B)y1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)y1").WithArguments("A", "B").WithLocation(10, 13), // (17,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // o = (A)x2; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)x2").WithArguments("B", "A").WithLocation(17, 13), // (18,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. // o = (A)y2; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)y2").WithArguments("B", "A").WithLocation(18, 13)); } [Fact] public void ExplicitCast_NestedNullability_02() { var source = @"interface I { } interface IIn { } interface IOut { } class A : I { } class B : IIn { } class C : IOut { } class D { static void F1(A x1, A y1) { object o; o = (I)x1; o = (I)x1; o = (I)y1; o = (I)y1; } static void F2(I x2, I y2) { object o; o = (A)x2; o = (A)x2; o = (A)y2; o = (A)y2; } static void F3(B x3, B y3) { object o; o = (IIn)x3; o = (IIn)x3; o = (IIn)y3; o = (IIn)y3; } static void F4(IIn x4, IIn y4) { object o; o = (B)x4; o = (B)x4; o = (B)y4; o = (B)y4; } static void F5(C x5, C y5) { object o; o = (IOut)x5; o = (IOut)x5; o = (IOut)y5; o = (IOut)y5; } static void F6(IOut x6, IOut y6) { object o; o = (C)x6; o = (C)x6; o = (C)y6; o = (C)y6; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ExplicitCast_NestedNullability_03() { var source = @"interface I { } interface IIn { } interface IOut { } sealed class A : I { } sealed class B : IIn { } sealed class C : IOut { } class D { static void F1(A x1, A y1) { object o; o = (I)x1; o = (I)x1; // 1 o = (I)y1; // 2 o = (I)y1; } static void F2(I x2, I y2) { object o; o = (A)x2; o = (A)x2; // 3 o = (A)y2; // 4 o = (A)y2; } static void F3(B x3, B y3) { object o; o = (IIn)x3; o = (IIn)x3; // 5 o = (IIn)y3; o = (IIn)y3; } static void F4(IIn x4, IIn y4) { object o; o = (B)x4; o = (B)x4; o = (B)y4; // 6 o = (B)y4; } static void F5(C x5, C y5) { object o; o = (IOut)x5; o = (IOut)x5; o = (IOut)y5; // 7 o = (IOut)y5; } static void F6(IOut x6, IOut y6) { object o; o = (C)x6; o = (C)x6; // 8 o = (C)y6; o = (C)y6; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // o = (I)x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(I)x1").WithArguments("A", "I").WithLocation(13, 13), // (14,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'I'. // o = (I)y1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(I)y1").WithArguments("A", "I").WithLocation(14, 13), // (21,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'A'. // o = (A)x2; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)x2").WithArguments("I", "A").WithLocation(21, 13), // (22,13): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'A'. // o = (A)y2; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)y2").WithArguments("I", "A").WithLocation(22, 13), // (29,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'IIn'. // o = (IIn)x3; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(IIn)x3").WithArguments("B", "IIn").WithLocation(29, 13), // (38,13): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'B'. // o = (B)y4; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)y4").WithArguments("IIn", "B").WithLocation(38, 13), // (46,13): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'IOut'. // o = (IOut)y5; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(IOut)y5").WithArguments("C", "IOut").WithLocation(46, 13), // (53,13): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'C'. // o = (C)x6; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(C)x6").WithArguments("IOut", "C").WithLocation(53, 13)); } [Fact] [WorkItem(35334, "https://github.com/dotnet/roslyn/issues/35334")] public void ExplicitCast_UserDefined_01() { var source = @"class A1 { public static implicit operator B?(A1? a) => new B(); } class A2 { public static implicit operator B?(A2 a) => new B(); } class A3 { public static implicit operator B(A3? a) => new B(); } class A4 { public static implicit operator B(A4 a) => new B(); } class B { } class C { static void F1(A1? x1, A1 y1) { B? b; b = ((B)x1)/*T:B?*/; b = ((B?)x1)/*T:B?*/; b = ((B)y1)/*T:B?*/; b = ((B?)y1)/*T:B?*/; } static void F2(A2? x2, A2 y2) { B? b; b = ((B)x2)/*T:B?*/; b = ((B?)x2)/*T:B?*/; b = ((B)y2)/*T:B?*/; b = ((B?)y2)/*T:B?*/; } static void F3(A3? x3, A3 y3) { B? b; b = ((B)x3)/*T:B!*/; b = ((B?)x3)/*T:B?*/; b = ((B)y3)/*T:B!*/; b = ((B?)y3)/*T:B?*/; } static void F4(A4? x4, A4 y4) { B? b; b = ((B)x4)/*T:B!*/; b = ((B?)x4)/*T:B?*/; b = ((B)y4)/*T:B!*/; b = ((B?)y4)/*T:B?*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // b = ((B)x1)/*T:B?*/; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)x1").WithLocation(23, 14), // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // b = ((B)y1)/*T:B?*/; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)y1").WithLocation(25, 14), // (31,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A2.implicit operator B?(A2 a)'. // b = ((B)x2)/*T:B?*/; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("a", "A2.implicit operator B?(A2 a)").WithLocation(31, 17), // (31,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // b = ((B)x2)/*T:B?*/; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)x2").WithLocation(31, 14), // (32,18): warning CS8604: Possible null reference argument for parameter 'a' in 'A2.implicit operator B?(A2 a)'. // b = ((B?)x2)/*T:B?*/; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("a", "A2.implicit operator B?(A2 a)").WithLocation(32, 18), // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // b = ((B)y2)/*T:B?*/; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)y2").WithLocation(33, 14), // (47,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A4.implicit operator B(A4 a)'. // b = ((B)x4)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("a", "A4.implicit operator B(A4 a)").WithLocation(47, 17), // (48,18): warning CS8604: Possible null reference argument for parameter 'a' in 'A4.implicit operator B(A4 a)'. // b = ((B?)x4)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("a", "A4.implicit operator B(A4 a)").WithLocation(48, 18)); comp.VerifyTypes(); } [Fact] public void ExplicitCast_UserDefined_02() { var source = @"class A where T : class? { } class B { public static implicit operator A(B b) => throw null!; } class C { public static implicit operator A(C c) => throw null!; static void F1(B x1) { var y1 = (A)x1; var z1 = (A)x1; // 1 } static void F2(C x2) { var y2 = (A)x2; // 2 var z2 = (A)x2; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,18): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // var z1 = (A)x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)x1").WithArguments("A", "A").WithLocation(14, 18), // (18,18): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // var y2 = (A)x2; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(A)x2").WithArguments("A", "A").WithLocation(18, 18)); } [Fact] public void ExplicitCast_UserDefined_03() { var source = @"class A1 where T : class { public static implicit operator B(A1 a) => throw null!; } class A2 where T : class { public static implicit operator B(A2 a) => throw null!; } class B { } class C where T : class { static void F1(A1 x1, A1 y1) { B x; B y; x = ((B)x1)/*T:B!*/; y = ((B)x1)/*T:B!*/; x = ((B)y1)/*T:B!*/; y = ((B)y1)/*T:B!*/; } static void F2(A2 x2, A2 y2) { B x; B y; x = ((B)x2)/*T:B!*/; y = ((B)x2)/*T:B!*/; x = ((B)y2)/*T:B!*/; y = ((B)y2)/*T:B!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,27): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'A1'. Nullability of type argument 'T?' doesn't match 'class' constraint. // static void F1(A1 x1, A1 y1) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "x1").WithArguments("A1", "T", "T?").WithLocation(12, 27), // (17,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // y = ((B)x1)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)x1").WithArguments("B", "B").WithLocation(17, 14), // (19,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // y = ((B)y1)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)y1").WithArguments("B", "B").WithLocation(19, 14), // (21,27): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'A2'. Nullability of type argument 'T?' doesn't match 'class' constraint. // static void F2(A2 x2, A2 y2) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "x2").WithArguments("A2", "T", "T?").WithLocation(21, 27), // (26,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // y = ((B)x2)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)x2").WithArguments("B", "B").WithLocation(26, 14), // (27,14): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // x = ((B)y2)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(B)y2").WithArguments("B", "B").WithLocation(27, 14)); comp.VerifyTypes(); } [Fact] public void ExplicitCast_StaticType() { var source = @"static class C { static object F(object? x) => (C)x; static object? G(object? y) => (C?)y; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,35): error CS0716: Cannot convert to static type 'C' // static object F(object? x) => (C)x; Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C)x").WithArguments("C").WithLocation(3, 35), // (3,35): warning CS8600: Converting null literal or possible null value to non-nullable type. // static object F(object? x) => (C)x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)x").WithLocation(3, 35), // (4,36): error CS0716: Cannot convert to static type 'C' // static object? G(object? y) => (C?)y; Diagnostic(ErrorCode.ERR_ConvertToStaticClass, "(C?)y").WithArguments("C").WithLocation(4, 36) ); } [Fact] public void ForEach_01() { var source = @"class Enumerable { public Enumerator GetEnumerator() => new Enumerator(); } class Enumerator { public object Current => throw null!; public bool MoveNext() => false; } class C { static void F(Enumerable e) { foreach (var x in e) x.ToString(); foreach (string y in e) y.ToString(); foreach (string? z in e) z.ToString(); // 1 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,13): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(19, 13)); } [Fact] public void ForEach_02() { var source = @"class Enumerable { public Enumerator GetEnumerator() => new Enumerator(); } class Enumerator { public object? Current => throw null!; public bool MoveNext() => false; } class C { static void F(Enumerable e) { foreach (var x in e) x.ToString(); foreach (object y in e) y.ToString(); foreach (object? z in e) z.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(15, 13), // (16,25): warning CS8605: Possible null reference assignment to iteration variable // foreach (object y in e) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "y").WithLocation(16, 25), // (17,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(17, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(19, 13)); } [Fact] public void ForEach_03() { var source = @"using System.Collections; namespace System { public class Object { public string ToString() => throw null!; } public abstract class ValueType { } public struct Void { } public struct Boolean { } public class String { } public struct Enum { } public class Attribute { } public struct Int32 { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) => throw null!; public bool AllowMultiple { get; set; } } public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } public class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message) => throw null!; } } namespace System.Collections { public interface IEnumerable { IEnumerator GetEnumerator(); } public interface IEnumerator { object? Current { get; } bool MoveNext(); } } class Enumerable : IEnumerable { IEnumerator IEnumerable.GetEnumerator() => throw null!; } class C { static void F(Enumerable e) { foreach (var x in e) x.ToString(); foreach (object y in e) y.ToString(); } static void G(IEnumerable e) { foreach (var z in e) z.ToString(); foreach (object w in e) w.ToString(); } }"; var comp = CreateEmptyCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (50,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(50, 13), // (51,25): warning CS8605: Possible null reference assignment to iteration variable // foreach (object y in e) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "y").WithLocation(51, 25), // (52,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(52, 13), // (57,13): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(57, 13), // (58,25): warning CS8605: Possible null reference assignment to iteration variable // foreach (object w in e) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "w").WithLocation(58, 25), // (59,13): warning CS8602: Dereference of a possibly null reference. // w.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w").WithLocation(59, 13)); } // z.ToString() should warn if IEnumerator.Current is annotated as `object?`. [Fact] public void ForEach_04() { var source = @"using System.Collections; using System.Collections.Generic; class C { static void F(IEnumerable cx, object?[] cy) { foreach (var x in cx) x.ToString(); foreach (object? y in cy) y.ToString(); foreach (object? z in (IEnumerable)cx) z.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13), // (10,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(10, 13)); } [Fact] public void ForEach_05() { var source = @"class C { static void F1(dynamic c) { foreach (var x in c) x.ToString(); foreach (object? y in c) y.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void ForEach_06() { var source = @"using System.Collections; using System.Collections.Generic; class C : IEnumerable where T : class { IEnumerator IEnumerable.GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } class P { static void F(C c) where T : class { foreach (var x in c) x.ToString(); foreach (T? y in c) y.ToString(); foreach (T z in c) z.ToString(); foreach (object w in c) w.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,28): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'T?' doesn't match 'class' constraint. // static void F(C c) where T : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "c").WithArguments("C", "T", "T?").WithLocation(10, 28), // (13,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(15, 13), // (16,20): warning CS8605: Possible null reference assignment to iteration variable // foreach (T z in c) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "z").WithLocation(16, 20), // (17,13): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(17, 13), // (18,25): warning CS8605: Possible null reference assignment to iteration variable // foreach (object w in c) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "w").WithLocation(18, 25), // (19,13): warning CS8602: Dereference of a possibly null reference. // w.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w").WithLocation(19, 13)); } [Fact] public void ForEach_07() { var source = @"struct S where T : class { public E GetEnumerator() => new E(); } struct E where T : class { public T Current => throw null!; public bool MoveNext() => false; } class P { static void F1() where T : class { foreach (var x1 in new S()) x1.ToString(); foreach (T y1 in new S()) y1.ToString(); foreach (T? z1 in new S()) z1.ToString(); foreach (object? w1 in new S()) w1.ToString(); } static void F2() where T : class { foreach (var x2 in new S()) x2.ToString(); foreach (T y2 in new S()) y2.ToString(); foreach (T? z2 in new S()) z2.ToString(); foreach (object? w2 in new S()) w2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (25,34): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'S'. Nullability of type argument 'T?' doesn't match 'class' constraint. // foreach (var x2 in new S()) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "T?").WithArguments("S", "T", "T?").WithLocation(25, 34), // (26,13): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(26, 13), // (27,20): warning CS8605: Possible null reference assignment to iteration variable // foreach (T y2 in new S()) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "y2").WithLocation(27, 20), // (27,32): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'S'. Nullability of type argument 'T?' doesn't match 'class' constraint. // foreach (T y2 in new S()) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "T?").WithArguments("S", "T", "T?").WithLocation(27, 32), // (28,13): warning CS8602: Dereference of a possibly null reference. // y2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(28, 13), // (29,33): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'S'. Nullability of type argument 'T?' doesn't match 'class' constraint. // foreach (T? z2 in new S()) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "T?").WithArguments("S", "T", "T?").WithLocation(29, 33), // (30,13): warning CS8602: Dereference of a possibly null reference. // z2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(30, 13), // (31,38): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'S'. Nullability of type argument 'T?' doesn't match 'class' constraint. // foreach (object? w2 in new S()) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "T?").WithArguments("S", "T", "T?").WithLocation(31, 38), // (32,13): warning CS8602: Dereference of a possibly null reference. // w2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(32, 13)); } [Fact] public void ForEach_08() { var source = @"using System.Collections.Generic; interface I { T P { get; } } interface IIn { } interface IOut { T P { get; } } static class C { static void F1(IEnumerable> x1, IEnumerable> y1) { foreach (I a1 in x1) a1.P.ToString(); foreach (I b1 in y1) b1.P.ToString(); } static void F2(IEnumerable> x2, IEnumerable> y2) { foreach (IIn a2 in x2) ; foreach (IIn b2 in y2) ; } static void F3(IEnumerable> x3, IEnumerable> y3) { foreach (IOut a3 in x3) a3.P.ToString(); foreach (IOut b3 in y3) b3.P.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,29): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // foreach (I a1 in x1) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a1").WithArguments("I", "I").WithLocation(9, 29), // (10,13): warning CS8602: Dereference of a possibly null reference. // a1.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a1.P").WithLocation(10, 13), // (11,28): warning CS8619: Nullability of reference types in value of type 'I' doesn't match target type 'I'. // foreach (I b1 in y1) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b1").WithArguments("I", "I").WithLocation(11, 28), // (16,31): warning CS8619: Nullability of reference types in value of type 'IIn' doesn't match target type 'IIn'. // foreach (IIn a2 in x2) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a2").WithArguments("IIn", "IIn").WithLocation(16, 31), // (24,13): warning CS8602: Dereference of a possibly null reference. // a3.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a3.P").WithLocation(24, 13), // (25,31): warning CS8619: Nullability of reference types in value of type 'IOut' doesn't match target type 'IOut'. // foreach (IOut b3 in y3) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b3").WithArguments("IOut", "IOut").WithLocation(25, 31)); } [Fact] public void ForEach_09() { var source = @"class A { } class B : A { } class C { static void F(A?[] c) { foreach (var a1 in c) a1.ToString(); foreach (A? a2 in c) a2.ToString(); foreach (A a3 in c) a3.ToString(); foreach (B? b1 in c) b1.ToString(); foreach (B b2 in c) b2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // a1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a1").WithLocation(8, 13), // (10,13): warning CS8602: Dereference of a possibly null reference. // a2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2").WithLocation(10, 13), // (11,20): warning CS8605: Possible null reference assignment to iteration variable // foreach (A a3 in c) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "a3").WithLocation(11, 20), // (12,13): warning CS8602: Dereference of a possibly null reference. // a3.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a3").WithLocation(12, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // b1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b1").WithLocation(14, 13), // (15,20): warning CS8605: Possible null reference assignment to iteration variable // foreach (B b2 in c) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "b2").WithLocation(15, 20), // (16,13): warning CS8602: Dereference of a possibly null reference. // b2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b2").WithLocation(16, 13)); } [Fact] [WorkItem(29971, "https://github.com/dotnet/roslyn/issues/29971")] public void ForEach_10() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class A { internal T F; } class B : A { } class C { static void F(A[] c) { foreach (var a1 in c) a1.F.ToString(); foreach (A a2 in c) a2.F.ToString(); foreach (A a3 in c) a3.F.ToString(); foreach (B b1 in c) b1.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // a1.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a1.F").WithLocation(13, 13), // (15,13): warning CS8602: Dereference of a possibly null reference. // a2.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2.F").WithLocation(15, 13), // (16,28): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // foreach (A a3 in c) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a3").WithArguments("A", "A").WithLocation(16, 28), // (18,20): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'B'. // foreach (B b1 in c) Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b1").WithArguments("A", "B").WithLocation(18, 20)); } [Fact] [WorkItem(29971, "https://github.com/dotnet/roslyn/issues/29971")] public void ForEach_11() { var source = @"using System.Collections.Generic; class A { public static implicit operator B?(A a) => null; } class B { } class C { static void F(IEnumerable e) { foreach (var x in e) x.ToString(); foreach (B y in e) y.ToString(); foreach (B? z in e) { z.ToString(); if (z != null) z.ToString(); } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,20): warning CS8605: Possible null reference assignment to iteration variable // foreach (B y in e) Diagnostic(ErrorCode.WRN_NullReferenceIterationVariable, "y").WithLocation(15, 20), // (16,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(16, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // z.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(19, 13)); } [WorkItem(23493, "https://github.com/dotnet/roslyn/issues/23493")] [Fact] public void ForEach_12() { var source = @"using System.Collections; using System.Collections.Generic; class C { static void F() { foreach (var x in (IEnumerable?)null) // 1 { } foreach (var y in (IEnumerable)default) // 2 { } foreach (var z in default(IEnumerable)) // 3 { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,27): error CS0186: Use of null is not valid in this context // foreach (var x in (IEnumerable?)null) // 1 Diagnostic(ErrorCode.ERR_NullNotValid, "(IEnumerable?)null").WithLocation(7, 27), // (10,27): error CS0186: Use of null is not valid in this context // foreach (var y in (IEnumerable)default) // 2 Diagnostic(ErrorCode.ERR_NullNotValid, "(IEnumerable)default").WithLocation(10, 27), // (13,27): error CS0186: Use of null is not valid in this context // foreach (var z in default(IEnumerable)) // 3 Diagnostic(ErrorCode.ERR_NullNotValid, "default(IEnumerable)").WithLocation(13, 27), // (7,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in (IEnumerable?)null) // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)null").WithLocation(7, 27), // (10,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var y in (IEnumerable)default) // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)default").WithLocation(10, 27), // (10,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in (IEnumerable)default) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)default").WithLocation(10, 27)); } [WorkItem(23493, "https://github.com/dotnet/roslyn/issues/23493")] [Fact] public void ForEach_13() { var source = @"using System.Collections; using System.Collections.Generic; class C { static void F1(object[]? c1) { foreach (var x in c1) // 1 { } foreach (var z in c1) // no cascade { } } static void F2(object[]? c1) { foreach (var y in (IEnumerable)c1) // 2 { } } static void F3(object[]? c1) { if (c1 == null) return; foreach (var z in c1) { } } static void F4(IList? c2) { foreach (var x in c2) // 3 { } } static void F5(IList? c2) { foreach (var y in (IEnumerable?)c2) // 4 { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in c1) // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(7, 27), // (16,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var y in (IEnumerable)c1) // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)c1").WithLocation(16, 27), // (16,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in (IEnumerable)c1) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)c1").WithLocation(16, 27), // (29,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in c2) // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(29, 27), // (35,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in (IEnumerable?)c2) // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)c2").WithLocation(35, 27)); } [WorkItem(23493, "https://github.com/dotnet/roslyn/issues/23493")] [Fact] public void ForEach_14() { var source = @"using System.Collections; using System.Collections.Generic; class C { static void F1(T t1) where T : class?, IEnumerable? { foreach (var x in t1) // 1 { } } static void F2(T t1) where T : class?, IEnumerable? { foreach (var y in (IEnumerable?)t1) // 2 { } } static void F3(T t1) where T : class?, IEnumerable? { foreach (var z in (IEnumerable)t1) // 3 { } } static void F4(T t2) where T : class? { foreach (var w in (IEnumerable?)t2) // 4 { } } static void F5(T t2) where T : class? { foreach (var v in (IEnumerable)t2) // 5 { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in t1) // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(7, 27), // (13,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in (IEnumerable?)t1) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)t1").WithLocation(13, 27), // (19,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var z in (IEnumerable)t1) // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)t1").WithLocation(19, 27), // (19,27): warning CS8602: Dereference of a possibly null reference. // foreach (var z in (IEnumerable)t1) // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t1").WithLocation(19, 27), // (25,27): warning CS8602: Dereference of a possibly null reference. // foreach (var w in (IEnumerable?)t2) // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)t2").WithLocation(25, 27), // (31,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var v in (IEnumerable)t2) // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)t2").WithLocation(31, 27), // (31,27): warning CS8602: Dereference of a possibly null reference. // foreach (var v in (IEnumerable)t2) // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t2").WithLocation(31, 27)); } [WorkItem(23493, "https://github.com/dotnet/roslyn/issues/23493")] [Fact] public void ForEach_15() { var source = @"using System.Collections; using System.Collections.Generic; class C { static void F1(T t1) where T : IEnumerable? { foreach (var x in t1) // 1 { } foreach (var x in t1) // no cascade { } } static void F2(T t1) where T : IEnumerable? { foreach (var w in (IEnumerable?)t1) // 2 { } } static void F3(T t1) where T : IEnumerable? { foreach (var v in (IEnumerable)t1) // 3 { } } static void F4(T t2) { foreach (var y in (IEnumerable?)t2) // 4 { } } static void F5(T t2) { foreach (var z in (IEnumerable)t2) // 5 { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in t1) // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(7, 27), // (16,27): warning CS8602: Dereference of a possibly null reference. // foreach (var w in (IEnumerable?)t1) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)t1").WithLocation(16, 27), // (22,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var v in (IEnumerable)t1) // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)t1").WithLocation(22, 27), // (22,27): warning CS8602: Dereference of a possibly null reference. // foreach (var v in (IEnumerable)t1) // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t1").WithLocation(22, 27), // (28,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in (IEnumerable?)t2) // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)t2").WithLocation(28, 27), // (34,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var z in (IEnumerable)t2) // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(IEnumerable)t2").WithLocation(34, 27), // (34,27): warning CS8602: Dereference of a possibly null reference. // foreach (var z in (IEnumerable)t2) // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable)t2").WithLocation(34, 27)); } [Fact] [WorkItem(29972, "https://github.com/dotnet/roslyn/issues/29972")] public void ForEach_16() { var source = @"using System.Collections; class Enumerable : IEnumerable { public IEnumerator? GetEnumerator() => null; } class C { static void F1(Enumerable e) { foreach (var x in e) // 1 { } foreach (var y in (IEnumerable?)e) // 2 { } foreach (var z in (IEnumerable)e) { } } static void F2(Enumerable? e) { foreach (var x in e) // 3 { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in e) // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e").WithLocation(10, 27), // (13,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in (IEnumerable?)e) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(IEnumerable?)e").WithLocation(13, 27), // (22,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in e) // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e").WithLocation(22, 27)); } [Fact] [WorkItem(29972, "https://github.com/dotnet/roslyn/issues/29972")] public void ForEach_17() { var source = @" class C { void M1(EnumerableType e) where EnumerableType : Enumerable where EnumeratorType : I? { foreach (var t in e) // 1 { t.ToString(); // 2 } } void M2(EnumerableType e) where EnumerableType : Enumerable where EnumeratorType : I { foreach (var t in e) { t.ToString(); // 3 } } } interface Enumerable where E : I? { E GetEnumerator(); } interface I { T Current { get; } bool MoveNext(); } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,27): warning CS8602: Dereference of a possibly null reference. // foreach (var t in e) // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e").WithLocation(8, 27), // (10,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(10, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(19, 13)); } [Fact] [WorkItem(34667, "https://github.com/dotnet/roslyn/issues/34667")] public void ForEach_18() { var source = @" using System.Collections.Generic; class Program { static void Main() { } static void F(IEnumerable source) { foreach (object[][] item in source) { } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,29): warning CS8619: Nullability of reference types in value of type 'object[]?[]' doesn't match target type 'object[][]'. // foreach (object[][] item in source) { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "item").WithArguments("object[]?[]", "object[][]").WithLocation(10, 29)); } [Fact] [WorkItem(35151, "https://github.com/dotnet/roslyn/issues/35151")] public void ForEach_19() { var source = @" using System.Collections; class C { void M1(IEnumerator e) { var enumerable1 = Create(e); foreach (var i in enumerable1) { } e = null; // 1 var enumerable2 = Create(e); foreach (var i in enumerable2) // 2 { } } void M2(IEnumerator? e) { var enumerable1 = Create(e); foreach (var i in enumerable1) // 3 { } if (e == null) return; var enumerable2 = Create(e); foreach (var i in enumerable2) { } } void M3(TEnumerator e) where TEnumerator : IEnumerator { var enumerable1 = Create(e); foreach (var i in enumerable1) { } e = default; // 4 var enumerable2 = Create(e); foreach (var i in enumerable2) // No warning here, safety warning was issued at 4 { } } void M4(TEnumerator e) where TEnumerator : IEnumerator? { var enumerable1 = Create(e); foreach (var i in enumerable1) // 5 { } if (e == null) return; var enumerable2 = Create(e); foreach (var i in enumerable2) // 6 { } } static Enumerable Create(T t) where T : IEnumerator? => throw null!; } class Enumerable where T : IEnumerator? { public T GetEnumerator() => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // e = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 13), // (14,27): warning CS8602: Dereference of a possibly null reference. // foreach (var i in enumerable2) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "enumerable2").WithLocation(14, 27), // (22,27): warning CS8602: Dereference of a possibly null reference. // foreach (var i in enumerable1) // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "enumerable1").WithLocation(22, 27), // (40,13): warning CS8653: A default expression introduces a null value when 'TEnumerator' is a non-nullable reference type. // e = default; // 4 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("TEnumerator").WithLocation(40, 13), // (50,27): warning CS8602: Dereference of a possibly null reference. // foreach (var i in enumerable1) // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "enumerable1").WithLocation(50, 27), // (56,27): warning CS8602: Dereference of a possibly null reference. // foreach (var i in enumerable2) // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "enumerable2").WithLocation(56, 27)); } [Fact] [WorkItem(35151, "https://github.com/dotnet/roslyn/issues/35151")] public void ForEach_20() { var source = @" using System.Collections.Generic; class C { void M1(string e) { var enumerable1 = Create(e); foreach (var s in enumerable1) { s.ToString(); } e = null; // 1 var enumerable2 = Create(e); foreach (var s in enumerable2) { s.ToString(); // 2 } } void M2(string? e) { var enumerable1 = Create(e); foreach (var s in enumerable1) { s.ToString(); // 3 } if (e == null) return; var enumerable2 = Create(e); foreach (var s in enumerable2) { s.ToString(); } } static Enumerable, U> Create(U u) => throw null!; } class Enumerable where T : IEnumerator? { public T GetEnumerator() => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // e = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 13), // (17,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(17, 13), // (26,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(26, 13)); } [Fact] [WorkItem(35151, "https://github.com/dotnet/roslyn/issues/35151")] public void ForEach_21() { var source = @" using System.Collections; using System.Collections.Generic; class C { void M1(string e) { var enumerable1 = Create(e); foreach (var s in enumerable1) { s.ToString(); } e = null; // 1 var enumerable2 = Create(e); foreach (var s in enumerable2) { s.ToString(); // 2 } } void M2(string? e) { var enumerable1 = Create(e); foreach (var s in enumerable1) { s.ToString(); // 3 } if (e == null) return; var enumerable2 = Create(e); foreach (var s in enumerable2) { s.ToString(); } } static Enumerable Create(T t) => throw null!; } class Enumerable : IEnumerable { public IEnumerator GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // e = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(15, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(19, 13), // (28,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(28, 13)); } [Fact] [WorkItem(35151, "https://github.com/dotnet/roslyn/issues/35151")] public void ForEach_22() { var source = @" using System.Collections; using System.Collections.Generic; class C { void M1(string e) { var enumerable1 = Create(e); foreach (var s in enumerable1) { s.ToString(); } e = null; // 1 var enumerable2 = Create(e); foreach (var s in enumerable2) { s.ToString(); // 2 } } void M2(string? e) { var enumerable1 = Create(e); foreach (var s in enumerable1) { s.ToString(); // 3 } if (e == null) return; var enumerable2 = Create(e); foreach (var s in enumerable2) { s.ToString(); } } static Enumerable Create(T t) => throw null!; } class Enumerable : IEnumerable { IEnumerator IEnumerable.GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // e = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(15, 13), // (19,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(19, 13), // (28,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(28, 13)); } [Fact] [WorkItem(33257, "https://github.com/dotnet/roslyn/issues/33257")] [WorkItem(35151, "https://github.com/dotnet/roslyn/issues/35151")] public void ForEach_23() { var source = @" class C { void M(string? s) { var l1 = new[] { s }; foreach (var x in l1) { x.ToString(); // 1 } if (s == null) return; var l2 = new[] { s }; foreach (var x in l2) { x.ToString(); } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(9, 13)); } [Fact] [WorkItem(33257, "https://github.com/dotnet/roslyn/issues/33257")] public void ForEach_Span() { var source = @" using System; class C { void M1(Span s1, Span s2) { foreach (var s in s1) { s.ToString(); } foreach (var s in s2) { s.ToString(); // 1 } } } "; var comp = CreateCompilationWithMscorlibAndSpan(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // s.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13)); } [Fact] [WorkItem(35151, "https://github.com/dotnet/roslyn/issues/35151")] public void ForEach_StringNotIEnumerable() { // In some frameworks, System.String doesn't implement IEnumerable, but for compat reasons the compiler // will still allow foreach'ing over these strings. var systemSource = @" namespace System { public class Object { } public struct Void { } public class ValueType { } public struct Boolean { } public struct Int32 { } public struct Char { public string ToString() => throw null!; } public class String { public int Length { get; } [System.Runtime.CompilerServices.IndexerName(""Chars"")] public char this[int i] => throw null!; } public interface IDisposable { void Dispose(); } public abstract class Attribute { protected Attribute() { } } } namespace System.Runtime.CompilerServices { using System; public sealed class IndexerNameAttribute: Attribute { public IndexerNameAttribute(String indexerName) {} } } namespace System.Reflection { using System; public sealed class DefaultMemberAttribute : Attribute { public DefaultMemberAttribute(String memberName) {} } } namespace System.Collections { public interface IEnumerable { IEnumerator GetEnumerator(); } public interface IEnumerator { object Current { get; } bool MoveNext(); } }"; var source = @" class C { void M(string s, string? s2) { foreach (var c in s) { c.ToString(); } s = null; // 1 foreach (var c in s) // 2 { c.ToString(); } foreach (var c in s2) // 3 { c.ToString(); } foreach (var c in (string)null) // 4 { } } }"; var comp = CreateEmptyCompilation(new[] { source, systemSource }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 13), // (12,27): warning CS8602: Dereference of a possibly null reference. // foreach (var c in s) // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(12, 27), // (17,27): warning CS8602: Dereference of a possibly null reference. // foreach (var c in s2) // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s2").WithLocation(17, 27), // (22,27): error CS0186: Use of null is not valid in this context // foreach (var c in (string)null) // 4 Diagnostic(ErrorCode.ERR_NullNotValid, "(string)null").WithLocation(22, 27), // (22,27): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach (var c in (string)null) // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)null").WithLocation(22, 27), // (22,27): warning CS8602: Dereference of a possibly null reference. // foreach (var c in (string)null) // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(string)null").WithLocation(22, 27)); } [Fact] public void ForEach_UnconstrainedTypeParameter() { var source = @"class C { void M(T parameter) { foreach (T local in new[] { parameter }) { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_01() { var source = @"class A { } class B { } class C { static void F(T? t) where T : A { } static void G(B? b) { F(b); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (8,9): error CS0311: The type 'B' cannot be used as type parameter 'T' in the generic type or method 'C.F(T?)'. There is no implicit reference conversion from 'B' to 'A'. // F(b); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "F").WithArguments("C.F(T?)", "A", "T", "B").WithLocation(8, 9)); } [Fact] public void TypeInference_02() { var source = @"interface I { } class C { static T F(I t) { throw new System.Exception(); } static void G(I x, I y) { F(x).ToString(); F(y).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // F(y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y)").WithLocation(11, 9)); } [Fact] public void TypeInference_03() { var source = @"interface I { } class C { static T F1(I t) { throw new System.Exception(); } static void G1(I x1, I y1) { F1(x1).ToString(); // 1 F1(y1).ToString(); // 2 } static T F2(I t) where T : class { throw new System.Exception(); } static void G2(I x2, I y2) { F2(x2).ToString(); // 3 F2(y2).ToString(); // 4 } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (4,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static T F1(I t) Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 22), // (10,12): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 't' in 'string C.F1(I t)'. // F1(x1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I", "I", "t", "string C.F1(I t)").WithLocation(10, 12), // (11,9): warning CS8602: Dereference of a possibly null reference. // F1(y1).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(y1)").WithLocation(11, 9), // (19,12): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 't' in 'string C.F2(I t)'. // F2(x2).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x2").WithArguments("I", "I", "t", "string C.F2(I t)").WithLocation(19, 12)); } [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] [Fact] public void TypeInference_LowerBounds_TopLevelNullability_01() { var source0 = @"public class A { public static A F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static void G(A? x, A y) { var z = A.F; F(x, x)/*T:A?*/; F(x, y)/*T:A?*/; F(x, z)/*T:A?*/; F(y, x)/*T:A?*/; F(y, y)/*T:A!*/; F(y, z)/*T:A!*/; F(z, x)/*T:A?*/; F(z, y)/*T:A!*/; F(z, z)/*T:A!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_LowerBounds_TopLevelNullability_02() { var source = @"class C { static T F(T x, T y) => throw null!; static void G(T t, U u) where T : class? where U : class, T { F(t, t)/*T:T*/; F(t, u)/*T:T*/; F(u, t)/*T:T*/; F(u, u)/*T:U!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [WorkItem(27961, "https://github.com/dotnet/roslyn/issues/27961")] [Fact] public void TypeInference_ExactBounds_TopLevelNullability_01() { var source0 = @"public class A { public static A F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(out T x, out T y) => throw null!; static void G(A? x, A y) { var z = A.F; F(out x, out x)/*T:A?*/; F(out x, out y)/*T:A!*/; F(out x, out z)/*T:A!*/; F(out y, out x)/*T:A!*/; F(out y, out y)/*T:A!*/; F(out y, out z)/*T:A!*/; F(out z, out x)/*T:A!*/; F(out z, out y)/*T:A!*/; F(out z, out z)/*T:A!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void TypeInference_LowerBounds_NestedNullability_Variant_01() { var source0 = @"public class A { public static I F; public static IIn FIn; public static IOut FOut; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static void G1(I x1, I y1) { var z1 = A.F/*T:I!*/; F(x1, x1)/*T:I!*/; F(x1, y1)/*T:I!*/; // 1 F(x1, z1)/*T:I!*/; F(y1, x1)/*T:I!*/; // 2 F(y1, y1)/*T:I!*/; F(y1, z1)/*T:I!*/; F(z1, x1)/*T:I!*/; F(z1, y1)/*T:I!*/; F(z1, z1)/*T:I!*/; } static void G2(IIn x2, IIn y2) { var z2 = A.FIn/*T:IIn!*/; F(x2, x2)/*T:IIn!*/; F(x2, y2)/*T:IIn!*/; F(x2, z2)/*T:IIn!*/; F(y2, x2)/*T:IIn!*/; F(y2, y2)/*T:IIn!*/; F(y2, z2)/*T:IIn!*/; F(z2, x2)/*T:IIn!*/; F(z2, y2)/*T:IIn!*/; F(z2, z2)/*T:IIn!*/; } static void G3(IOut x3, IOut y3) { var z3 = A.FOut/*T:IOut!*/; F(x3, x3)/*T:IOut!*/; F(x3, y3)/*T:IOut!*/; F(x3, z3)/*T:IOut!*/; F(y3, x3)/*T:IOut!*/; F(y3, y3)/*T:IOut!*/; F(y3, z3)/*T:IOut!*/; F(z3, x3)/*T:IOut!*/; F(z3, y3)/*T:IOut!*/; F(z3, z3)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (8,15): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'I C.F>(I x, I y)'. // F(x1, y1)/*T:I!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "y", "I C.F>(I x, I y)").WithLocation(8, 15), // (10,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'I C.F>(I x, I y)'. // F(y1, x1)/*T:I!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "x", "I C.F>(I x, I y)").WithLocation(10, 11) ); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void TypeInference_LowerBounds_NestedNullability_Variant_02() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"public interface IOut { } class C { static T F(T x, T y) => throw null!; static T F(T x, T y, T z) => throw null!; static IOut CreateIOut(B t, B u) => throw null!; static void G(B x, B y) { var z = A.F/*T:B!*/; var xx = CreateIOut(x, x)/*T:IOut!*/; var xy = CreateIOut(x, y)/*T:IOut!*/; var xz = CreateIOut(x, z)/*T:IOut!*/; F(xx, xy)/*T:IOut!*/; F(xx, xz)/*T:IOut!*/; F(CreateIOut(y, x), xx)/*T:IOut!*/; F(CreateIOut(y, z), CreateIOut(z, x))/*T:IOut!*/; F(xx, xy, xz)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void TypeInference_LowerBounds_NestedNullability_Variant_03() { var source0 = @"public class A { public static I F; public static IIn FIn; public static IOut FOut; } public interface I { } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static I Create1(T t) => throw null!; static void G1(I> x1, I> y1) { var z1 = Create1(A.FOut)/*T:I!>!*/; F(x1, x1)/*T:I!>!*/; F(x1, y1)/*T:I!>!*/; // 1 F(x1, z1)/*T:I!>!*/; F(y1, x1)/*T:I!>!*/; // 2 F(y1, y1)/*T:I!>!*/; F(y1, z1)/*T:I!>!*/; F(z1, x1)/*T:I!>!*/; F(z1, y1)/*T:I!>!*/; F(z1, z1)/*T:I!>!*/; } static IOut Create2(T t) => throw null!; static void G2(IOut> x2, IOut> y2) { var z2 = Create2(A.FIn)/*T:IOut!>!*/; F(x2, x2)/*T:IOut!>!*/; F(x2, y2)/*T:IOut!>!*/; F(x2, z2)/*T:IOut!>!*/; F(y2, x2)/*T:IOut!>!*/; F(y2, y2)/*T:IOut!>!*/; F(y2, z2)/*T:IOut!>!*/; F(z2, x2)/*T:IOut!>!*/; F(z2, y2)/*T:IOut!>!*/; F(z2, z2)/*T:IOut!>!*/; } static IIn Create3(T t) => throw null!; static void G3(IIn> x3, IIn> y3) { var z3 = Create3(A.FOut)/*T:IIn!>!*/; F(x3, x3)/*T:IIn!>!*/; F(x3, y3)/*T:IIn!>!*/; F(x3, z3)/*T:IIn!>!*/; F(y3, x3)/*T:IIn!>!*/; F(y3, y3)/*T:IIn!>!*/; F(y3, z3)/*T:IIn!>!*/; F(z3, x3)/*T:IIn!>!*/; F(z3, y3)/*T:IIn!>!*/; F(z3, z3)/*T:IIn!>!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (9,11): warning CS8620: Nullability of reference types in argument of type 'I>' doesn't match target type 'I>' for parameter 'x' in 'I> C.F>>(I> x, I> y)'. // F(x1, y1)/*T:I!>!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I>", "I>", "x", "I> C.F>>(I> x, I> y)").WithLocation(9, 11), // (11,15): warning CS8620: Nullability of reference types in argument of type 'I>' doesn't match target type 'I>' for parameter 'y' in 'I> C.F>>(I> x, I> y)'. // F(y1, x1)/*T:I!>!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I>", "I>", "y", "I> C.F>>(I> x, I> y)").WithLocation(11, 15) ); } [Fact] public void TypeInference_ExactBounds_TopLevelNullability_02() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(B x, B y) => throw null!; static void G(B x, B y) { var z = A.F/*T:B!*/; F(x, x)/*T:string?*/; F(x, y)/*T:string!*/; // 1 F(x, z)/*T:string?*/; F(y, x)/*T:string!*/; // 2 F(y, y)/*T:string!*/; F(y, z)/*T:string!*/; F(z, x)/*T:string?*/; F(z, y)/*T:string!*/; F(z, z)/*T:string!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (8,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'string C.F(B x, B y)'. // F(x, y)/*T:string!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "string C.F(B x, B y)").WithLocation(8, 11), // (10,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string C.F(B x, B y)'. // F(y, x)/*T:string!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "string C.F(B x, B y)").WithLocation(10, 14) ); } [Fact] public void TypeInference_ExactBounds_NestedNullability() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class Program { static T F(T x, T y, T z) => throw null!; static void G(B x, B y) { var z = A.F/*T:B!*/; F(x, x, x)/*T:B!*/; F(x, x, y)/*T:B!*/; // 1 2 F(x, x, z)/*T:B!*/; F(x, y, x)/*T:B!*/; // 3 4 F(x, y, y)/*T:B!*/; // 5 F(x, y, z)/*T:B!*/; // 6 F(x, z, x)/*T:B!*/; F(x, z, y)/*T:B!*/; // 7 F(x, z, z)/*T:B!*/; F(y, x, x)/*T:B!*/; // 8 9 F(y, x, y)/*T:B!*/; // 10 F(y, x, z)/*T:B!*/; // 11 F(y, y, x)/*T:B!*/; // 12 F(y, y, y)/*T:B!*/; F(y, y, z)/*T:B!*/; F(y, z, x)/*T:B!*/; // 13 F(y, z, y)/*T:B!*/; F(y, z, z)/*T:B!*/; F(z, x, x)/*T:B!*/; F(z, x, y)/*T:B!*/; // 14 F(z, x, z)/*T:B!*/; F(z, y, x)/*T:B!*/; // 15 F(z, y, y)/*T:B!*/; F(z, y, z)/*T:B!*/; F(z, z, x)/*T:B!*/; F(z, z, y)/*T:B!*/; F(z, z, z)/*T:B!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. // F(x, x, y)/*T:B!*/; // 1 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(8, 11), // (8,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. // F(x, x, y)/*T:B!*/; // 1 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(8, 14), // (10,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. // F(x, y, x)/*T:B!*/; // 3 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(10, 11), // (10,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. // F(x, y, x)/*T:B!*/; // 3 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(10, 17), // (11,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. // F(x, y, y)/*T:B!*/; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(11, 11), // (12,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. // F(x, y, z)/*T:B!*/; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(12, 11), // (14,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B Program.F>(B x, B y, B z)'. // F(x, z, y)/*T:B!*/; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B Program.F>(B x, B y, B z)").WithLocation(14, 11), // (16,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. // F(y, x, x)/*T:B!*/; // 8 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(16, 14), // (16,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. // F(y, x, x)/*T:B!*/; // 8 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(16, 17), // (17,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. // F(y, x, y)/*T:B!*/; // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(17, 14), // (18,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. // F(y, x, z)/*T:B!*/; // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(18, 14), // (19,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. // F(y, y, x)/*T:B!*/; // 12 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(19, 17), // (22,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. // F(y, z, x)/*T:B!*/; // 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(22, 17), // (26,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B Program.F>(B x, B y, B z)'. // F(z, x, y)/*T:B!*/; // 14 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "y", "B Program.F>(B x, B y, B z)").WithLocation(26, 14), // (28,17): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'z' in 'B Program.F>(B x, B y, B z)'. // F(z, y, x)/*T:B!*/; // 15 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "z", "B Program.F>(B x, B y, B z)").WithLocation(28, 17) ); comp.VerifyTypes(); } [Fact] public void TypeInference_ExactAndLowerBounds_TopLevelNullability() { var source0 = @"public class A { public static B F; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, B y) => throw null!; static B CreateB(T t) => throw null!; static void G(string? x, string y) { var z = A.F /*T:B!*/; F(x, CreateB(x))/*T:string?*/; F(x, CreateB(y))/*T:string?*/; // 1 F(x, z)/*T:string?*/; F(y, CreateB(x))/*T:string?*/; F(y, CreateB(y))/*T:string!*/; F(y, z)/*T:string!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (9,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string? C.F(string? x, B y)'. // F(x, CreateB(y))/*T:string?*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(y)").WithArguments("B", "B", "y", "string? C.F(string? x, B y)").WithLocation(9, 14) ); } [Fact] public void TypeInference_ExactAndUpperBounds_TopLevelNullability() { var source0 = @"public class A { public static IIn FIn; public static B FB; } public interface IIn { } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(IIn x, B y) => throw null!; static IIn CreateIIn(T t) => throw null!; static B CreateB(T t) => throw null!; static void G(string? x, string y) { var zin = A.FIn/*T:IIn!*/; var zb = A.FB/*T:B!*/; F(CreateIIn(x), CreateB(x))/*T:string?*/; F(CreateIIn(x), CreateB(y))/*T:string!*/; F(CreateIIn(x), zb)/*T:string!*/; F(CreateIIn(y), CreateB(x))/*T:string!*/; // 1 F(CreateIIn(y), CreateB(y))/*T:string!*/; F(CreateIIn(y), zb)/*T:string!*/; F(zin, CreateB(x))/*T:string!*/; F(zin, CreateB(y))/*T:string!*/; F(zin, zb)/*T:string!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (13,25): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'string C.F(IIn x, B y)'. // F(CreateIIn(y), CreateB(x))/*T:string!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(x)").WithArguments("B", "B", "y", "string C.F(IIn x, B y)").WithLocation(13, 25) ); comp.VerifyTypes(); } [Fact] [WorkItem(29837, "https://github.com/dotnet/roslyn/issues/29837")] public void TypeInference_MixedBounds_NestedNullability() { var source0 = @"public class A { public static IIn F1; public static IOut F2; } public interface IIn { } public interface IOut { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static void F1(bool b, IIn x1, IIn y1) { var z1 = A.F1/*T:IIn!*/; F(x1, x1)/*T:IIn!*/; F(x1, y1)/*T:IIn!*/; // 1 F(x1, z1)/*T:IIn!*/; F(y1, x1)/*T:IIn!*/; // 2 F(y1, y1)/*T:IIn!*/; F(y1, z1)/*T:IIn!*/; F(z1, x1)/*T:IIn!*/; F(z1, y1)/*T:IIn!*/; F(z1, z1)/*T:IIn!*/; } static void F2(bool b, IOut x2, IOut y2) { var z2 = A.F2/*T:IOut!*/; F(x2, x2)/*T:IOut!*/; F(x2, y2)/*T:IOut!*/; // 3 F(x2, z2)/*T:IOut!*/; F(y2, x2)/*T:IOut!*/; // 4 F(y2, y2)/*T:IOut!*/; F(y2, z2)/*T:IOut!*/; F(z2, x2)/*T:IOut!*/; F(z2, y2)/*T:IOut!*/; F(z2, z2)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (8,15): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'IIn C.F>(IIn x, IIn y)'. // F(x1, y1)/*T:IIn!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("IIn", "IIn", "y", "IIn C.F>(IIn x, IIn y)").WithLocation(8, 15), // (10,11): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'x' in 'IIn C.F>(IIn x, IIn y)'. // F(y1, x1)/*T:IIn!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("IIn", "IIn", "x", "IIn C.F>(IIn x, IIn y)").WithLocation(10, 11), // (21,15): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'y' in 'IOut C.F>(IOut x, IOut y)'. // F(x2, y2)/*T:IOut!*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IOut", "IOut", "y", "IOut C.F>(IOut x, IOut y)").WithLocation(21, 15), // (23,11): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'x' in 'IOut C.F>(IOut x, IOut y)'. // F(y2, x2)/*T:IOut!*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IOut", "IOut", "x", "IOut C.F>(IOut x, IOut y)").WithLocation(23, 11) ); } [Fact] public void TypeInference_LowerBounds_NestedNullability_MismatchedTypes() { var source = @"interface IOut { } class Program { static T F(T x, T y) => throw null!; static void G(IOut x, IOut y) { F(x, y)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // Ideally we'd infer IOut but the spec doesn't require merging nullability // across distinct types (in this case, the lower bounds IOut and IOut). // Instead, method type inference infers IOut and a warning is reported // converting the second argument to the inferred parameter type. comp.VerifyTypes(); comp.VerifyDiagnostics( // (7,14): warning CS8620: Nullability of reference types in argument of type 'IOut' doesn't match target type 'IOut' for parameter 'y' in 'IOut Program.F>(IOut x, IOut y)'. // F(x, y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IOut", "IOut", "y", "IOut Program.F>(IOut x, IOut y)").WithLocation(7, 14)); } [Fact] public void TypeInference_LowerAndUpperBounds_NestedNullability() { var source = @"interface IIn { } interface IOut { } class Program { static T FIn(T x, T y, IIn z) => throw null!; static T FOut(T x, T y, IOut z) => throw null!; static IIn CreateIIn(T t) => throw null!; static IOut CreateIOut(T t) => throw null!; static void G1(IIn x1, IIn y1) { FIn(x1, y1, CreateIIn(x1))/*T:IIn!*/; // 1 FIn(x1, y1, CreateIIn(y1))/*T:IIn!*/; FOut(x1, y1, CreateIOut(x1))/*T:IIn!*/; FOut(x1, y1, CreateIOut(y1))/*T:IIn!*/; } static void G2(IOut x2, IOut y2) { FIn(x2, y2, CreateIIn(x2))/*T:IOut!*/; FIn(x2, y2, CreateIIn(y2))/*T:IOut!*/; // 2 FOut(x2, y2, CreateIOut(x2))/*T:IOut!*/; FOut(x2, y2, CreateIOut(y2))/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // Ideally we'd fail to infer nullability for // 1 and // 2 rather than inferring the // wrong nullability and then reporting a warning converting the arguments. // (See MethodTypeInferrer.TryMergeAndReplaceIfStillCandidate which ignores // the variance used merging earlier candidates when merging later candidates.) comp.VerifyTypes(); comp.VerifyDiagnostics( // (11,21): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'z' in 'IIn Program.FIn>(IIn x, IIn y, IIn> z)'. // FIn(x1, y1, CreateIIn(x1))/*T:IIn!*/; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateIIn(x1)").WithArguments("IIn>", "IIn>", "z", "IIn Program.FIn>(IIn x, IIn y, IIn> z)").WithLocation(11, 21), // (19,21): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'z' in 'IOut Program.FIn>(IOut x, IOut y, IIn> z)'. // FIn(x2, y2, CreateIIn(y2))/*T:IOut!*/; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateIIn(y2)").WithArguments("IIn>", "IIn>", "z", "IOut Program.FIn>(IOut x, IOut y, IIn> z)").WithLocation(19, 21)); } [Fact] public void TypeInference_05() { var source = @"class C { static T F(T x, T? y) where T : class => x; static void G(C? x, C y) { F(x, x).ToString(); F(x, y).ToString(); F(y, x).ToString(); F(y, y).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,9): warning CS8634: The type 'C?' cannot be used as type parameter 'T' in the generic type or method 'C.F(T, T?)'. Nullability of type argument 'C?' doesn't match 'class' constraint. // F(x, x).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F(T, T?)", "T", "C?").WithLocation(6, 9), // (6,9): warning CS8602: Dereference of a possibly null reference. // F(x, x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x, x)").WithLocation(6, 9), // (7,9): warning CS8634: The type 'C?' cannot be used as type parameter 'T' in the generic type or method 'C.F(T, T?)'. Nullability of type argument 'C?' doesn't match 'class' constraint. // F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F(T, T?)", "T", "C?").WithLocation(7, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // F(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x, y)").WithLocation(7, 9)); } [Fact] public void TypeInference_06() { var source = @"class C { static T F(T t, U u) where U : T => t; static void G(C? x, C y) { F(x, x).ToString(); // warning: may be null F(x, y).ToString(); // warning may be null F(y, x).ToString(); // warning: x does not satisfy U constraint F(y, y).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // F(x, x).ToString(); // warning: may be null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x, x)").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // F(x, y).ToString(); // warning may be null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x, y)").WithLocation(7, 9), // (8,9): warning CS8631: The type 'C?' cannot be used as type parameter 'U' in the generic type or method 'C.F(T, U)'. Nullability of type argument 'C?' doesn't match constraint type 'C'. // F(y, x).ToString(); // warning: x does not satisfy U constraint Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F").WithArguments("C.F(T, U)", "C", "U", "C?").WithLocation(8, 9)); } [Fact] public void TypeInference_LowerBounds_NestedNullability_MismatchedNullability() { var source0 = @"public class A { public static A F; public static A G; } public class A { } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static B CreateB(A t, A u) => throw null!; static void G(A t1, A t2, A u1, A u2) { var t3 = A.F/*T:A!*/; var u3 = A.G/*T:A!*/; var x = CreateB(t1, u2)/*T:B!*/; var y = CreateB(t2, u1)/*T:B!*/; var z = CreateB(t1, u3)/*T:B!*/; var w = CreateB(t3, u2)/*T:B!*/; F(x, y)/*T:B!*/; F(x, z)/*T:B!*/; F(x, w)/*T:B!*/; F(y, z)/*T:B!*/; F(y, w)/*T:B!*/; F(w, z)/*T:B!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (13,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B C.F>(B x, B y)'. // F(x, y)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(13, 11), // (13,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B C.F>(B x, B y)'. // F(x, y)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(13, 14), // (16,14): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'y' in 'B C.F>(B x, B y)'. // F(y, z)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(16, 14), // (17,11): warning CS8620: Nullability of reference types in argument of type 'B' doesn't match target type 'B' for parameter 'x' in 'B C.F>(B x, B y)'. // F(y, w)/*T:B!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(17, 11) ); } [Fact] public void TypeInference_UpperBounds_NestedNullability_MismatchedNullability() { var source0 = @"public class A { public static X F; public static X G; } public interface IIn { } public class B { } public class X { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(IIn x, IIn y) => throw null!; static IIn> CreateB(X t, X u) => throw null!; static void G(X t1, X t2, X u1, X u2) { var t3 = A.F/*T:X!*/; var u3 = A.G/*T:X!*/; var x = CreateB(t1, u2)/*T:IIn!>!*/; var y = CreateB(t2, u1)/*T:IIn!>!*/; var z = CreateB(t1, u3)/*T:IIn!>!*/; var w = CreateB(t3, u2)/*T:IIn!>!*/; F(x, y)/*T:B!*/; // 1 2 F(x, z)/*T:B!*/; F(x, w)/*T:B!*/; F(y, z)/*T:B!*/; // 3 F(y, w)/*T:B!*/; // 4 F(w, z)/*T:B!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (13,11): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'x' in 'B C.F>(IIn> x, IIn> y)'. // F(x, y)/*T:B!*/; // 1 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(13, 11), // (13,14): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'y' in 'B C.F>(IIn> x, IIn> y)'. // F(x, y)/*T:B!*/; // 1 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(13, 14), // (16,14): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'y' in 'B C.F>(IIn> x, IIn> y)'. // F(y, z)/*T:B!*/; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(16, 14), // (17,11): warning CS8620: Nullability of reference types in argument of type 'IIn>' doesn't match target type 'IIn>' for parameter 'x' in 'B C.F>(IIn> x, IIn> y)'. // F(y, w)/*T:B!*/; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(17, 11) ); } [Fact] public void TypeInference_LowerBounds_NestedNullability_TypeParameters() { var source = @"interface IOut { } class C { static T F(T x, T y) => throw null!; static void G(IOut x, IOut y) where T : class { F(x, x)/*T:IOut!*/; F(x, y)/*T:IOut!*/; F(y, x)/*T:IOut!*/; F(y, y)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] [WorkItem(33346, "https://github.com/dotnet/roslyn/issues/33346")] public void TypeInference_LowerBounds_NestedNullability_Arrays() { var source0 = @"public class A { public static string[] F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static void G(string?[] x, string[] y) { var z = A.F/*T:string[]!*/; F(x, x)/*T:string?[]!*/; F(x, y)/*T:string?[]!*/; F(x, z)/*T:string?[]!*/; F(y, x)/*T:string?[]!*/; F(y, y)/*T:string![]!*/; F(y, z)/*T:string[]!*/; F(z, x)/*T:string?[]!*/; F(z, y)/*T:string[]!*/; F(z, z)/*T:string[]!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_LowerBounds_NestedNullability_Dynamic() { var source = @"interface IOut { } class C { static T F(T x, T y) => throw null!; static void G(IOut x, IOut y) { F(x, x)/*T:IOut!*/; F(x, y)/*T:IOut!*/; F(y, x)/*T:IOut!*/; F(y, y)/*T:IOut!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_LowerBounds_NestedNullability_Pointers() { var source = @"unsafe class C { static T F(T x, T y) => throw null!; static void G(object?* x, object* y) // 1 { _ = z/*T:object**/; F(x, x)/*T:object?**/; // 2 F(x, y)/*T:object!**/; // 3 F(x, z)/*T:object?**/; // 4 F(y, x)/*T:object!**/; // 5 F(y, y)/*T:object!**/; // 6 F(y, z)/*T:object!**/; // 7 F(z, x)/*T:object?**/; // 8 F(z, y)/*T:object!**/; // 9 F(z, z)/*T:object**/; // 10 } #nullable disable public static object* z = null; // 11 }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(TestOptions.UnsafeDebugDll)); comp.VerifyTypes(); comp.VerifyDiagnostics( // (4,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') // static void G(object?* x, object* y) Diagnostic(ErrorCode.ERR_ManagedAddr, "object?*").WithArguments("object").WithLocation(4, 19), // (4,31): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') // static void G(object?* x, object* y) Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object").WithLocation(4, 31), // (7,9): error CS0306: The type 'object*' may not be used as a type argument // F(x, x)/*T:object?**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(7, 9), // (8,9): error CS0306: The type 'object*' may not be used as a type argument // F(x, y)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(8, 9), // (9,9): error CS0306: The type 'object*' may not be used as a type argument // F(x, z)/*T:object?**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(9, 9), // (10,9): error CS0306: The type 'object*' may not be used as a type argument // F(y, x)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(10, 9), // (11,9): error CS0306: The type 'object*' may not be used as a type argument // F(y, y)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(11, 9), // (12,9): error CS0306: The type 'object*' may not be used as a type argument // F(y, z)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(12, 9), // (13,9): error CS0306: The type 'object*' may not be used as a type argument // F(z, x)/*T:object?**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(13, 9), // (14,9): error CS0306: The type 'object*' may not be used as a type argument // F(z, y)/*T:object!**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(14, 9), // (15,9): error CS0306: The type 'object*' may not be used as a type argument // F(z, z)/*T:object**/; Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("object*").WithLocation(15, 9), // (20,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') // public static object* z = null; Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object").WithLocation(20, 19) ); } [Fact] public void TypeInference_LowerBounds_NestedNullability_Tuples() { var source0 = @"public class A { public static B F; public static B G; } public class B { } "; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static (T, U) Create(B t, B u) => throw null!; static void G(B t1, B t2, B u1, B u2) { var t3 = A.F/*T:B!*/; var u3 = A.G/*T:B!*/; var x = Create(t1, u2)/*T:(object?, string!)*/; var y = Create(t2, u1)/*T:(object!, string?)*/; var z = Create(t1, u3)/*T:(object?, string)*/; var w = Create(t3, u2)/*T:(object, string!)*/; F(x, y)/*T:(object?, string?)*/; F(x, z)/*T:(object?, string)*/; F(x, w)/*T:(object?, string!)*/; F(y, z)/*T:(object?, string?)*/; F(y, w)/*T:(object, string?)*/; F(w, z)/*T:(object?, string)*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_LowerBounds_NestedNullability_Tuples_Variant() { var source0 = @"public class A { public static (object, string) F; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"interface I { } interface IIn { } interface IOut { } class C { static T F(T x, T y) => throw null!; static I CreateI(T t) => throw null!; static void G1(I<(object, string)> x1, I<(object?, string?)> y1) { var z1 = CreateI(A.F)/*T:I<(object, string)>!*/; F(x1, x1)/*T:I<(object!, string!)>!*/; F(x1, y1)/*T:I<(object!, string!)>!*/; F(x1, z1)/*T:I<(object!, string!)>!*/; F(y1, x1)/*T:I<(object!, string!)>!*/; F(y1, y1)/*T:I<(object?, string?)>!*/; F(y1, z1)/*T:I<(object?, string?)>!*/; F(z1, x1)/*T:I<(object!, string!)>!*/; F(z1, y1)/*T:I<(object?, string?)>!*/; F(z1, z1)/*T:I<(object, string)>!*/; } static IIn CreateIIn(T t) => throw null!; static void G2(IIn<(object, string)> x2, IIn<(object?, string?)> y2) { var z2 = CreateIIn(A.F)/*T:IIn<(object, string)>!*/; F(x2, x2)/*T:IIn<(object!, string!)>!*/; F(x2, y2)/*T:IIn<(object!, string!)>!*/; F(x2, z2)/*T:IIn<(object!, string!)>!*/; F(y2, x2)/*T:IIn<(object!, string!)>!*/; F(y2, y2)/*T:IIn<(object?, string?)>!*/; F(y2, z2)/*T:IIn<(object, string)>!*/; F(z2, x2)/*T:IIn<(object!, string!)>!*/; F(z2, y2)/*T:IIn<(object, string)>!*/; F(z2, z2)/*T:IIn<(object, string)>!*/; } static IOut CreateIOut(T t) => throw null!; static void G3(IOut<(object, string)> x3, IOut<(object?, string?)> y3) { var z3 = CreateIOut(A.F)/*T:IOut<(object, string)>!*/; F(x3, x3)/*T:IOut<(object!, string!)>!*/; F(x3, y3)/*T:IOut<(object?, string?)>!*/; F(x3, z3)/*T:IOut<(object, string)>!*/; F(y3, x3)/*T:IOut<(object?, string?)>!*/; F(y3, y3)/*T:IOut<(object?, string?)>!*/; F(y3, z3)/*T:IOut<(object?, string?)>!*/; F(z3, x3)/*T:IOut<(object, string)>!*/; F(z3, y3)/*T:IOut<(object?, string?)>!*/; F(z3, z3)/*T:IOut<(object, string)>!*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (12,15): warning CS8620: Nullability of reference types in argument of type 'I<(object?, string?)>' doesn't match target type 'I<(object, string)>' for parameter 'y' in 'I<(object, string)> C.F>(I<(object, string)> x, I<(object, string)> y)'. // F(x1, y1)/*T:I<(object, string)>!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I<(object?, string?)>", "I<(object, string)>", "y", "I<(object, string)> C.F>(I<(object, string)> x, I<(object, string)> y)").WithLocation(12, 15), // (14,11): warning CS8620: Nullability of reference types in argument of type 'I<(object?, string?)>' doesn't match target type 'I<(object, string)>' for parameter 'x' in 'I<(object, string)> C.F>(I<(object, string)> x, I<(object, string)> y)'. // F(y1, x1)/*T:I<(object, string)>!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I<(object?, string?)>", "I<(object, string)>", "x", "I<(object, string)> C.F>(I<(object, string)> x, I<(object, string)> y)").WithLocation(14, 11), // (26,15): warning CS8620: Nullability of reference types in argument of type 'IIn<(object?, string?)>' doesn't match target type 'IIn<(object, string)>' for parameter 'y' in 'IIn<(object, string)> C.F>(IIn<(object, string)> x, IIn<(object, string)> y)'. // F(x2, y2)/*T:IIn<(object!, string!)>!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IIn<(object?, string?)>", "IIn<(object, string)>", "y", "IIn<(object, string)> C.F>(IIn<(object, string)> x, IIn<(object, string)> y)").WithLocation(26, 15), // (28,11): warning CS8620: Nullability of reference types in argument of type 'IIn<(object?, string?)>' doesn't match target type 'IIn<(object, string)>' for parameter 'x' in 'IIn<(object, string)> C.F>(IIn<(object, string)> x, IIn<(object, string)> y)'. // F(y2, x2)/*T:IIn<(object!, string!)>!*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y2").WithArguments("IIn<(object?, string?)>", "IIn<(object, string)>", "x", "IIn<(object, string)> C.F>(IIn<(object, string)> x, IIn<(object, string)> y)").WithLocation(28, 11), // (40,11): warning CS8620: Nullability of reference types in argument of type 'IOut<(object, string)>' doesn't match target type 'IOut<(object?, string?)>' for parameter 'x' in 'IOut<(object?, string?)> C.F>(IOut<(object?, string?)> x, IOut<(object?, string?)> y)'. // F(x3, y3)/*T:IOut<(object?, string?)>?*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x3").WithArguments("IOut<(object, string)>", "IOut<(object?, string?)>", "x", "IOut<(object?, string?)> C.F>(IOut<(object?, string?)> x, IOut<(object?, string?)> y)").WithLocation(40, 11), // (42,15): warning CS8620: Nullability of reference types in argument of type 'IOut<(object, string)>' doesn't match target type 'IOut<(object?, string?)>' for parameter 'y' in 'IOut<(object?, string?)> C.F>(IOut<(object?, string?)> x, IOut<(object?, string?)> y)'. // F(y3, x3)/*T:IOut<(object?, string?)>?*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x3").WithArguments("IOut<(object, string)>", "IOut<(object?, string?)>", "y", "IOut<(object?, string?)> C.F>(IOut<(object?, string?)> x, IOut<(object?, string?)> y)").WithLocation(42, 15)); } [Fact] public void Assignment_NestedNullability_MismatchedNullability() { var source0 = @"public class A { public static object F; public static string G; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class B { } class C { static B CreateB(T t, U u) => throw null!; static void G(object? t1, object t2, string? u1, string u2) { var t3 = A.F/*T:object!*/; var u3 = A.G/*T:string!*/; var x0 = CreateB(t1, u2)/*T:B!*/; var y0 = CreateB(t2, u1)/*T:B!*/; var z0 = CreateB(t1, u3)/*T:B!*/; var w0 = CreateB(t3, u2)/*T:B!*/; var x = x0; var y = y0; var z = z0; var w = w0; x = y0; // 1 x = z0; x = w0; // 2 y = z0; // 3 y = w0; // 4 w = z0; // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (17,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // x = y0; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y0").WithArguments("B", "B").WithLocation(17, 13), // (19,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // x = w0; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w0").WithArguments("B", "B").WithLocation(19, 13), // (20,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // y = z0; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z0").WithArguments("B", "B").WithLocation(20, 13), // (21,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // y = w0; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "w0").WithArguments("B", "B").WithLocation(21, 13), // (22,13): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'B'. // w = z0; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "z0").WithArguments("B", "B").WithLocation(22, 13) ); } [Fact] public void TypeInference_09() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static T F(I x, I y) { throw new System.Exception(); } static void G1(I x1, I y1) { F(x1, x1)/*T:string!*/.ToString(); F(x1, y1)/*T:string!*/.ToString(); F(y1, x1)/*T:string!*/.ToString(); F(y1, y1)/*T:string?*/.ToString(); } static T F(IIn x, IIn y) { throw new System.Exception(); } static void G2(IIn x2, IIn y2) { F(x2, x2)/*T:string!*/.ToString(); F(x2, y2)/*T:string!*/.ToString(); F(y2, x2)/*T:string!*/.ToString(); F(y2, y2)/*T:string?*/.ToString(); } static T F(IOut x, IOut y) { throw new System.Exception(); } static void G3(IOut x3, IOut y3) { F(x3, x3)/*T:string!*/.ToString(); F(x3, y3)/*T:string?*/.ToString(); F(y3, x3)/*T:string?*/.ToString(); F(y3, y3)/*T:string?*/.ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyTypes(); comp.VerifyDiagnostics( // (13,15): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'string C.F(I x, I y)'. // F(x1, y1)/*T:string!*/.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "y", "string C.F(I x, I y)").WithLocation(13, 15), // (14,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'string C.F(I x, I y)'. // F(y1, x1)/*T:string!*/.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "x", "string C.F(I x, I y)").WithLocation(14, 11), // (15,9): warning CS8602: Dereference of a possibly null reference. // F(y1, y1)/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y1, y1)").WithLocation(15, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // F(y2, y2)/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y2, y2)").WithLocation(26, 9), // (35,9): warning CS8602: Dereference of a possibly null reference. // F(x3, y3)/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x3, y3)").WithLocation(35, 9), // (36,9): warning CS8602: Dereference of a possibly null reference. // F(y3, x3)/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y3, x3)").WithLocation(36, 9), // (37,9): warning CS8602: Dereference of a possibly null reference. // F(y3, y3)/*T:string?*/.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y3, y3)").WithLocation(37, 9)); } [Fact] public void TypeInference_10() { var source = @"interface I { } interface IIn { } interface IOut { } class C { static T F(I x, I y) where T : class { throw new System.Exception(); } static void G1(I x1, I y1) { F(x1, x1).ToString(); // 1 F(x1, y1).ToString(); F(y1, x1).ToString(); // 2 and 3 F(y1, y1).ToString(); // 4 } static T F(IIn x, IIn y) where T : class { throw new System.Exception(); } static void G2(IIn x2, IIn y2) { F(x2, x2).ToString(); // 5 F(x2, y2).ToString(); F(y2, x2).ToString(); // 6 F(y2, y2).ToString(); } static T F(IOut x, IOut y) where T : class { throw new System.Exception(); } static void G3(IOut x3, IOut y3) { F(x3, x3).ToString(); F(x3, y3).ToString(); F(y3, x3).ToString(); // 7 F(y3, y3).ToString(); // 8 } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (12,15): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'string C.F(I x, I y)'. // F(x1, x1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I", "I", "y", "string C.F(I x, I y)").WithLocation(12, 15), // (14,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'string C.F(I x, I y)'. // F(y1, x1).ToString(); // 2 and 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "x", "string C.F(I x, I y)").WithLocation(14, 11), // (14,15): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'y' in 'string C.F(I x, I y)'. // F(y1, x1).ToString(); // 2 and 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x1").WithArguments("I", "I", "y", "string C.F(I x, I y)").WithLocation(14, 15), // (15,11): warning CS8620: Nullability of reference types in argument of type 'I' doesn't match target type 'I' for parameter 'x' in 'string C.F(I x, I y)'. // F(y1, y1).ToString(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y1").WithArguments("I", "I", "x", "string C.F(I x, I y)").WithLocation(15, 11), // (23,15): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'string C.F(IIn x, IIn y)'. // F(x2, x2).ToString(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x2").WithArguments("IIn", "IIn", "y", "string C.F(IIn x, IIn y)").WithLocation(23, 15), // (25,15): warning CS8620: Nullability of reference types in argument of type 'IIn' doesn't match target type 'IIn' for parameter 'y' in 'string C.F(IIn x, IIn y)'. // F(y2, x2).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x2").WithArguments("IIn", "IIn", "y", "string C.F(IIn x, IIn y)").WithLocation(25, 15), // (36,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.F(IOut, IOut)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // F(y3, x3).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F(IOut, IOut)", "T", "string?").WithLocation(36, 9), // (36,9): warning CS8602: Dereference of a possibly null reference. // F(y3, x3).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y3, x3)").WithLocation(36, 9), // (37,9): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C.F(IOut, IOut)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // F(y3, y3).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F(IOut, IOut)", "T", "string?").WithLocation(37, 9), // (37,9): warning CS8602: Dereference of a possibly null reference. // F(y3, y3).ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y3, y3)").WithLocation(37, 9)); } [Fact] public void TypeInference_11() { var source0 = @"public class A { public T F; } public class UnknownNull { public A A1; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source1 = @"#pragma warning disable 8618 public class MaybeNull { public A A2; } public class NotNull { public A A3; }"; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp1.VerifyDiagnostics(); var ref1 = comp1.EmitToImageReference(); var source = @"class C { static T F(T x, T y) => throw null!; static void F1(UnknownNull x1, UnknownNull y1) { F(x1.A1, y1.A1)/*T:A!*/.F.ToString(); } static void F2(UnknownNull x2, MaybeNull y2) { F(x2.A1, y2.A2)/*T:A!*/.F.ToString(); } static void F3(MaybeNull x3, UnknownNull y3) { F(x3.A2, y3.A1)/*T:A!*/.F.ToString(); } static void F4(MaybeNull x4, MaybeNull y4) { F(x4.A2, y4.A2)/*T:A!*/.F.ToString(); } static void F5(UnknownNull x5, NotNull y5) { F(x5.A1, y5.A3)/*T:A!*/.F.ToString(); } static void F6(NotNull x6, UnknownNull y6) { F(x6.A3, y6.A1)/*T:A!*/.F.ToString(); } static void F7(MaybeNull x7, NotNull y7) { F(x7.A2, y7.A3)/*T:A!*/.F.ToString(); } static void F8(NotNull x8, MaybeNull y8) { F(x8.A3, y8.A2)/*T:A!*/.F.ToString(); } static void F9(NotNull x9, NotNull y9) { F(x9.A3, y9.A3)/*T:A!*/.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0, ref1 }); comp.VerifyTypes(); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // F(x2.A1, y2.A2)/*T:A!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x2.A1, y2.A2)/*T:A!*/.F").WithLocation(10, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // F(x3.A2, y3.A1)/*T:A!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x3.A2, y3.A1)/*T:A!*/.F").WithLocation(14, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // F(x4.A2, y4.A2)/*T:A!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x4.A2, y4.A2)/*T:A!*/.F").WithLocation(18, 9), // (30,11): warning CS8620: Nullability of reference types in argument of type 'A' doesn't match target type 'A' for parameter 'x' in 'A C.F>(A x, A y)'. // F(x7.A2, y7.A3)/*T:A!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x7.A2").WithArguments("A", "A", "x", "A C.F>(A x, A y)").WithLocation(30, 11), // (34,18): warning CS8620: Nullability of reference types in argument of type 'A' doesn't match target type 'A' for parameter 'y' in 'A C.F>(A x, A y)'. // F(x8.A3, y8.A2)/*T:A!*/.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y8.A2").WithArguments("A", "A", "y", "A C.F>(A x, A y)").WithLocation(34, 18) ); } [Fact] public void TypeInference_12() { var source = @"class C { internal T F; } class C { static C Create(T t) { return new C(); } static void F(object? x) { if (x == null) { Create(x).F = null; var y = Create(x); y.F = null; } else { Create(x).F = null; // warn var y = Create(x); y.F = null; // warn } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,16): warning CS8618: Non-nullable field 'F' is uninitialized. // internal T F; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(3, 16), // (21,27): warning CS8625: Cannot convert null literal to non-nullable reference type. // Create(x).F = null; // warn Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(21, 27), // (23,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // y.F = null; // warn Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(23, 19)); } [Fact] public void TypeInference_ArgumentOrder() { var source = @"interface I { T P { get; } } class C { static T F(I x, I y) => x.P; static void M(I x, I y) { F(y: y, x: x).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // F(y: y, x: x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y: y, x: x)").WithLocation(10, 9)); } [Fact] public void TypeInference_Local() { var source = @"class C { static T F(T t) => t; static void G() { object x = new object(); object? y = x; F(x).ToString(); F(y).ToString(); y = null; F(y).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // F(y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y)").WithLocation(11, 9)); } [Fact] public void TypeInference_Call() { var source = @"class C { static T F(T t) => t; static object F1() => new object(); static object? F2() => null; static void G() { F(F1()).ToString(); F(F2()).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // F(F2()).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(F2())").WithLocation(9, 9)); } [Fact] public void TypeInference_Property() { var source = @"class C { static T F(T t) => t; static object P => new object(); static object? Q => null; static void G() { F(P).ToString(); F(Q).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // F(Q).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(Q)").WithLocation(9, 9)); } [Fact] public void TypeInference_FieldAccess() { var source = @"class C { static T F(T t) => t; static object F1 = new object(); static object? F2 = null; static void G() { F(F1).ToString(); F(F2).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // F(F2).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(F2)").WithLocation(9, 9)); } [Fact] public void TypeInference_Literal() { var source = @"class C { static T F(T t) => t; static void G() { F(0).ToString(); F('A').ToString(); F(""B"").ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_Default() { var source = @"class C { static T F(T t) => t; static void G() { F(default(object)).ToString(); F(default(int)).ToString(); F(default(string)).ToString(); F(default).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,9): error CS0411: The type arguments for method 'C.F(T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // F(default).ToString(); Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("C.F(T)").WithLocation(9, 9), // (6,9): warning CS8602: Dereference of a possibly null reference. // F(default(object)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(default(object))").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // F(default(string)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(default(string))").WithLocation(8, 9)); } [Fact] public void TypeInference_Tuple_01() { var source = @"class C { static (T, U) F((T, U) t) => t; static void G(string x, string? y) { var t = (x, y); F(t).Item1.ToString(); F(t).Item2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // F(t).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(t).Item2").WithLocation(8, 9)); } [Fact] public void TypeInference_Tuple_02() { var source = @"class C { static T F(T t) => t; static void G(string x, string? y) { var t = (x, y); F(t).Item1.ToString(); F(t).Item2.ToString(); F(t).x.ToString(); F(t).y.ToString(); var u = (a: x, b: y); F(u).Item1.ToString(); F(u).Item2.ToString(); F(u).a.ToString(); F(u).b.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // F(t).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(t).Item2").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // F(t).y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(t).y").WithLocation(10, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // F(u).Item2.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(u).Item2").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // F(u).b.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(u).b").WithLocation(15, 9)); } [Fact] public void TypeInference_Tuple_03() { var source = @"class C { static void F(object? x, object? y) { if (x == null) return; var t = (x, y); t.x.ToString(); t.y.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(8, 9)); } [Fact] public void TypeInference_ObjectCreation() { var source = @"class C { static T F(T t) => t; static void G() { F(new C { }).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_DelegateCreation() { var source = @"delegate void D(); class C { static T F(T t) => t; static void G() { F(new D(G)).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_BinaryOperator() { var source = @"class C { static T F(T t) => t; static void G(string x, string? y) { F(x + x).ToString(); F(x + y).ToString(); F(y + x).ToString(); F(y + y).ToString(); } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics(); } [Fact] public void TypeInference_NullCoalescingOperator() { var source = @"class C { static T F(T t) => t; static void G(int i, object x, object? y) { switch (i) { case 1: F(x ?? x).ToString(); break; case 2: F(x ?? y).ToString(); break; case 3: F(y ?? x).ToString(); break; case 4: F(y ?? y).ToString(); break; } } }"; var comp = CreateCompilation( new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,17): warning CS8602: Dereference of a possibly null reference. // F(x ?? x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x ?? x)").WithLocation(9, 17), // (12,17): warning CS8602: Dereference of a possibly null reference. // F(x ?? y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(x ?? y)").WithLocation(12, 17), // (18,17): warning CS8602: Dereference of a possibly null reference. // F(y ?? y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(y ?? y)").WithLocation(18, 17)); } [Fact] public void Members_Fields() { var source = @"#pragma warning disable 0649 class C { internal string? F; } class Program { static void F(C a) { G(a.F); if (a.F != null) G(a.F); C b = new C(); G(b.F); if (b.F != null) G(b.F); } static void G(string s) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.G(string s)'. // G(a.F); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a.F").WithArguments("s", "void Program.G(string s)").WithLocation(10, 11), // (13,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.G(string s)'. // G(b.F); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b.F").WithArguments("s", "void Program.G(string s)").WithLocation(13, 11)); } [Fact] public void Members_Fields_UnconstrainedType() { var source = @" class C { internal T field = default; static void F(C a, bool c) { if (c) a.field.ToString(); // 1 else if (a.field != null) a.field.ToString(); C b = new C(); if (c) b.field.ToString(); // 2 else if (b.field != null) b.field.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,24): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // internal T field = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(4, 24), // (8,16): warning CS8602: Dereference of a possibly null reference. // if (c) a.field.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.field").WithLocation(8, 16), // (11,16): warning CS8602: Dereference of a possibly null reference. // if (c) b.field.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.field").WithLocation(11, 16)); } [Fact] public void Members_AutoProperties() { var source = @"class C { internal string? P { get; set; } } class Program { static void F(C a) { G(a.P); if (a.P != null) G(a.P); C b = new C(); G(b.P); if (b.P != null) G(b.P); } static void G(string s) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.G(string s)'. // G(a.P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a.P").WithArguments("s", "void Program.G(string s)").WithLocation(9, 11), // (12,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.G(string s)'. // G(b.P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b.P").WithArguments("s", "void Program.G(string s)").WithLocation(12, 11)); } [Fact] public void Members_Properties() { var source = @"class C { internal string? P { get { throw new System.Exception(); } set { } } } class Program { static void F(C a) { G(a.P); if (a.P != null) G(a.P); C b = new C(); G(b.P); if (b.P != null) G(b.P); } static void G(string s) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.G(string s)'. // G(a.P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a.P").WithArguments("s", "void Program.G(string s)").WithLocation(9, 11), // (12,11): warning CS8604: Possible null reference argument for parameter 's' in 'void Program.G(string s)'. // G(b.P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b.P").WithArguments("s", "void Program.G(string s)").WithLocation(12, 11)); } [Fact] public void Members_AutoPropertyFromConstructor() { var source = @"class A { protected static void F(string s) { } protected string? P { get; set; } protected A() { F(P); if (P != null) F(P); } } class B : A { B() { F(this.P); if (this.P != null) F(this.P); F(base.P); if (base.P != null) F(base.P); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,11): warning CS8604: Possible null reference argument for parameter 's' in 'void A.F(string s)'. // F(this.P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "this.P").WithArguments("s", "void A.F(string s)").WithLocation(17, 11), // (19,11): warning CS8604: Possible null reference argument for parameter 's' in 'void A.F(string s)'. // F(base.P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "base.P").WithArguments("s", "void A.F(string s)").WithLocation(19, 11), // (9,11): warning CS8604: Possible null reference argument for parameter 's' in 'void A.F(string s)'. // F(P); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "P").WithArguments("s", "void A.F(string s)").WithLocation(9, 11)); } [Fact] public void ModifyMembers_01() { var source = @"#pragma warning disable 0649 class C { object? F; static void M(C c) { if (c.F == null) return; c = new C(); c.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // c.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.F").WithLocation(9, 9)); } [Fact] public void ModifyMembers_02() { var source = @"#pragma warning disable 0649 class A { internal C? C; } class B { internal A? A; } class C { internal B? B; } class Program { static void F() { object o; C? c = new C(); c.B = new B(); c.B.A = new A(); o = c.B.A; // 1 c.B.A = null; o = c.B.A; // 2 c.B = new B(); o = c.B.A; // 3 c.B = null; o = c.B.A; // 4 c = new C(); o = c.B.A; // 5 c = null; o = c.B.A; // 6 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (24,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.A; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.A").WithLocation(24, 13), // (26,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.A; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.A").WithLocation(26, 13), // (28,13): warning CS8602: Dereference of a possibly null reference. // o = c.B.A; // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.B").WithLocation(28, 13), // (28,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.A; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.A").WithLocation(28, 13), // (30,13): warning CS8602: Dereference of a possibly null reference. // o = c.B.A; // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.B").WithLocation(30, 13), // (30,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.A; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.A").WithLocation(30, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // o = c.B.A; // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(32, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // o = c.B.A; // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.B").WithLocation(32, 13), // (32,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.A; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.A").WithLocation(32, 13)); } [Fact] public void ModifyMembers_03() { var source = @"#pragma warning disable 0649 struct S { internal object? F; } class C { internal C? A; internal S B; } class Program { static void M() { object o; C c = new C(); o = c.A.A; // 1 o = c.B.F; // 1 c.A = new C(); c.B = new S(); o = c.A.A; // 2 o = c.B.F; // 2 c.A.A = new C(); c.B.F = new C(); o = c.A.A; // 3 o = c.B.F; // 3 c.A = new C(); c.B = new S(); o = c.A.A; // 4 o = c.B.F; // 4 c = new C(); o = c.A.A; // 5 o = c.B.F; // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,13): warning CS8602: Dereference of a possibly null reference. // o = c.A.A; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.A").WithLocation(17, 13), // (17,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(17, 13), // (18,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.F; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.F").WithLocation(18, 13), // (21,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(21, 13), // (22,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.F; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.F").WithLocation(22, 13), // (29,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(29, 13), // (30,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.F; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.F").WithLocation(30, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // o = c.A.A; // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.A").WithLocation(32, 13), // (32,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(32, 13), // (33,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.F; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.F").WithLocation(33, 13)); } [Fact] public void ModifyMembers_Properties() { var source = @"#pragma warning disable 0649 struct S { internal object? P { get; set; } } class C { internal C? A { get; set; } internal S B; } class Program { static void M() { object o; C c = new C(); o = c.A.A; // 1 o = c.B.P; // 1 c.A = new C(); c.B = new S(); o = c.A.A; // 2 o = c.B.P; // 2 c.A.A = new C(); c.B.P = new C(); o = c.A.A; // 3 o = c.B.P; // 3 c.A = new C(); c.B = new S(); o = c.A.A; // 4 o = c.B.P; // 4 c = new C(); o = c.A.A; // 5 o = c.B.P; // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,13): warning CS8602: Dereference of a possibly null reference. // o = c.A.A; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.A").WithLocation(17, 13), // (17,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(17, 13), // (18,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.P; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.P").WithLocation(18, 13), // (21,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(21, 13), // (22,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.P; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.P").WithLocation(22, 13), // (29,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(29, 13), // (30,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.P; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.P").WithLocation(30, 13), // (32,13): warning CS8602: Dereference of a possibly null reference. // o = c.A.A; // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.A").WithLocation(32, 13), // (32,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.A.A; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.A.A").WithLocation(32, 13), // (33,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = c.B.P; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c.B.P").WithLocation(33, 13)); } [Fact] public void ModifyMembers_Struct() { var source = @"#pragma warning disable 0649 struct A { internal object? F; } struct B { internal A A; internal object? G; } class Program { static void F() { object o; B b = new B(); b.G = new object(); b.A.F = new object(); o = b.G; // 1 o = b.A.F; // 1 b.A = default(A); o = b.G; // 2 o = b.A.F; // 2 b = default(B); o = b.G; // 3 o = b.A.F; // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = b.A.F; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b.A.F").WithLocation(23, 13), // (25,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = b.G; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b.G").WithLocation(25, 13), // (26,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = b.A.F; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "b.A.F").WithLocation(26, 13)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void ModifyMembers_StructPropertyExplicitAccessors() { var source = @"#pragma warning disable 0649 struct S { private object? _p; internal object? P { get { return _p; } set { _p = value; } } } class C { S F; void M() { object o; o = F.P; // 1 F.P = new object(); o = F.P; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = F.P; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "F.P").WithLocation(13, 13)); } [Fact] public void ModifyMembers_StructProperty() { var source = @"#pragma warning disable 0649 public struct S { public object? P { get; set; } } class C { S F; void M() { object o; o = F.P; // 1 F.P = new object(); o = F.P; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = F.P; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "F.P").WithLocation(12, 13)); } [Fact] public void ModifyMembers_StructPropertyFromMetadata() { var source0 = @"public struct S { public object? P { get; set; } }"; var comp0 = CreateCompilation(source0); var ref0 = comp0.EmitToImageReference(); var source = @"#pragma warning disable 0649 class C { S F; void M() { object o; o = F.P; // 1 F.P = new object(); o = F.P; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = F.P; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "F.P").WithLocation(8, 13)); } [Fact] public void ModifyMembers_ClassPropertyNoBackingField() { var source = @"#pragma warning disable 0649 class C { object? P { get { return null; } set { } } void M() { object o; o = P; // 1 P = new object(); o = P; // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = P; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "P").WithLocation(8, 13)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void ModifyMembers_StructPropertyNoBackingField_01() { var source = @"#pragma warning disable 0649 struct S { internal object? P { get { return null; } set { } } } class C { S F; void M() { object o; o = F.P; // 1 F.P = new object(); o = F.P; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // o = F.P; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "F.P").WithLocation(12, 13)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void ModifyMembers_StructPropertyNoBackingField_02() { var source = @"struct S { internal T P => throw null!; } class Program { static S Create(T t) { return new S(); } static void F() where T : class, new() { T? x = null; var sx = Create(x); sx.P.ToString(); T? y = new T(); var sy = Create(y); sy.P.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Possible dereference of a null reference. // sx.P.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "sx.P").WithLocation(15, 9)); } // Calling a method should reset the state for members. [Fact] [WorkItem(29975, "https://github.com/dotnet/roslyn/issues/29975")] public void Members_CallMethod() { var source = @"#pragma warning disable 0649 class A { internal object? P { get; set; } } class B { internal A? Q { get; set; } } class Program { static void M() { object o; B b = new B() { Q = new A() { P = new object() } }; o = b.Q.P; // 1 b.Q.P.ToString(); o = b.Q.P; // 2 b.Q.ToString(); o = b.Q.P; // 3 b = new B() { Q = new A() { P = new object() } }; o = b.Q.P; // 4 b.ToString(); o = b.Q.P; // 5 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29975: Should report warnings. comp.VerifyDiagnostics(/*...*/); } [Fact] public void Members_ObjectInitializer() { var source = @"#pragma warning disable 0649 class A { internal object? F1; internal object? F2; } class B { internal A? G; } class Program { static void F() { (new B() { G = new A() { F1 = new object() } }).G.F1.ToString(); B b; b = new B() { G = new A() { F1 = new object() } }; b.G.F1.ToString(); // 1 b.G.F2.ToString(); // 1 b = new B() { G = new A() { F2 = new object() } }; b.G.F1.ToString(); // 2 b.G.F2.ToString(); // 2 b = new B() { G = new A() }; b.G.F1.ToString(); // 3 b.G.F2.ToString(); // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // b.G.F2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F2").WithLocation(19, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // b.G.F1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F1").WithLocation(21, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // b.G.F1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F1").WithLocation(24, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // b.G.F2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F2").WithLocation(25, 9)); } [Fact] public void Members_ObjectInitializer_Struct() { var source = @"#pragma warning disable 0649 struct A { internal object? F1; internal object? F2; } struct B { internal A G; } class Program { static void F() { (new B() { G = new A() { F1 = new object() } }).G.F1.ToString(); B b; b = new B() { G = new A() { F1 = new object() } }; b.G.F1.ToString(); // 1 b.G.F2.ToString(); // 1 b = new B() { G = new A() { F2 = new object() } }; b.G.F1.ToString(); // 2 b.G.F2.ToString(); // 2 b = new B() { G = new A() }; b.G.F1.ToString(); // 3 b.G.F2.ToString(); // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // b.G.F2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F2").WithLocation(19, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // b.G.F1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F1").WithLocation(21, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // b.G.F1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F1").WithLocation(24, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // b.G.F2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.G.F2").WithLocation(25, 9)); } [Fact] public void Members_ObjectInitializer_Properties() { var source = @"#pragma warning disable 0649 class A { internal object? P1 { get; set; } internal object? P2 { get; set; } } class B { internal A? Q { get; set; } } class Program { static void F() { (new B() { Q = new A() { P1 = new object() } }).Q.P1.ToString(); B b; b = new B() { Q = new A() { P1 = new object() } }; b.Q.P1.ToString(); // 1 b.Q.P2.ToString(); // 1 b = new B() { Q = new A() { P2 = new object() } }; b.Q.P1.ToString(); // 2 b.Q.P2.ToString(); // 2 b = new B() { Q = new A() }; b.Q.P1.ToString(); // 3 b.Q.P2.ToString(); // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // b.Q.P2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Q.P2").WithLocation(19, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // b.Q.P1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Q.P1").WithLocation(21, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // b.Q.P1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Q.P1").WithLocation(24, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // b.Q.P2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Q.P2").WithLocation(25, 9)); } [Fact] public void Members_ObjectInitializer_Events() { var source = @"delegate void D(); class C { event D? E; static void F() { C c; c = new C() { }; c.E.Invoke(); // warning c = new C() { E = F }; c.E.Invoke(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // c.E.Invoke(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.E").WithLocation(9, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Members_ObjectInitializer_DerivedType() { var source = @"#pragma warning disable 0649 class A { internal A? F; } class B : A { internal object? G; } class Program { static void Main() { A a; a = new B() { F = new A(), G = new object() }; a.F.ToString(); a = new A(); a.F.ToString(); // 1 a = new B() { F = new B() { F = new A() } }; a.F.ToString(); a.F.F.ToString(); a = new B() { G = new object() }; a.F.ToString(); // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,9): warning CS8602: Dereference of a possibly null reference. // a.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.F").WithLocation(18, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // a.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.F").WithLocation(23, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Members_Assignment() { var source = @"#pragma warning disable 0649 class A { internal A? F; } class B : A { internal object? G; } class Program { static void Main() { B b = new B(); A a; a = b; a.F.ToString(); // 1 b.F = new A(); a = b; a.F.ToString(); b = new B() { F = new B() { F = new A() } }; a = b; a.F.ToString(); a.F.F.ToString(); b = new B() { G = new object() }; a = b; a.F.ToString(); // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,9): warning CS8602: Dereference of a possibly null reference. // a.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.F").WithLocation(17, 9), // (27,9): warning CS8602: Dereference of a possibly null reference. // a.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.F").WithLocation(27, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_01() { var source = @"class A { internal object? FA; } class B : A { internal object FB = new object(); } class Program { static void F() { A a = new B() { FA = 1 }; a.FA.ToString(); a = new B() { FA = 2, FB = null }; // 1 ((B)a).FA.ToString(); ((B)a).FB.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // a = new B() { FA = 2, FB = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 36), // (17,9): warning CS8602: Dereference of a possibly null reference. // ((B)a).FB.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B)a).FB").WithLocation(17, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_02() { var source = @"class A { internal object? FA; } class B : A { internal object FB = new object(); } class Program { static void F() { B b = new B() { FA = 1 }; A a = b; a.FA.ToString(); a = new B() { FB = null }; // 1 b = (B)a; b.FB.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,28): warning CS8625: Cannot convert null literal to non-nullable reference type. // a = new B() { FB = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 28), // (18,9): warning CS8602: Dereference of a possibly null reference. // b.FB.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.FB").WithLocation(18, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_03() { var source = @"interface IA { object? PA { get; set; } } interface IB : IA { object PB { get; set; } } class Program { static void F(IB b) { b.PA = 1; b.PB = null; // 1 ((IA)b).PA.ToString(); ((IB)(object)b).PB.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // b.PB = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 16), // (16,9): warning CS8602: Dereference of a possibly null reference. // ((IB)(object)b).PB.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((IB)(object)b).PB").WithLocation(16, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_04() { var source = @"interface IA { object? PA { get; set; } } interface IB : IA { object PB { get; set; } } class Program { static void F(IB b) { b.PA = 1; b.PB = null; // 1 object o = b; b = o; // 2 b.PA.ToString(); b = (IB)o; b.PB.ToString(); // 3 ((IB)o).PA.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // b.PB = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 16), // (16,13): error CS0266: Cannot implicitly convert type 'object' to 'IB'. An explicit conversion exists (are you missing a cast?) // b = o; // 2 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "o").WithArguments("object", "IB").WithLocation(16, 13), // (19,9): warning CS8602: Dereference of a possibly null reference. // b.PB.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.PB").WithLocation(19, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_05() { var source = @"#pragma warning disable 0649 class C { internal object? F; } class Program { static void F(object x, object? y) { if (((C)x).F != null) ((C)x).F.ToString(); if (((C?)y)?.F != null) ((C)y).F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_06() { var source = @"class C { internal object F() => null!; } class Program { static void F(object? x) { if (((C?)x)?.F() != null) ((C)x).F().ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_07() { var source = @"interface I { object? P { get; } } class Program { static void F(object x, object? y) { if (((I)x).P != null) ((I)x).P.ToString(); if (((I?)y)?.P != null) ((I)y).P.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_08() { var source = @"interface I { object F(); } class Program { static void F(object? x) { if (((I?)x)?.F() != null) ((I)x).F().ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_09() { var source = @"class A { internal bool? F; } class B : A { } class Program { static void M(bool b1, bool b2) { A a; if (b1 ? b2 && (a = new B() { F = true }).F.Value : false) { } if (true ? b2 && (a = new B() { F = false }).F.Value : false) { } if (false ? false : b2 && (a = new B() { F = b1 }).F.Value) { } if (false ? b2 && (a = new B() { F = null }).F.Value : true) { } _ = (a = new B() { F = null }).F.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (25,13): warning CS8629: Nullable value type may be null. // _ = (a = new B() { F = null }).F.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(a = new B() { F = null }).F").WithLocation(25, 13)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_ReferenceConversions_10() { var source = @"class A { internal object? FA; } class B : A { internal object FB = new object(); } class Program { static void F() { A a = new B() { FB = null }; // 1 a = new A() { FA = 1 }; a.FA.ToString(); ((B)a).FB.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,30): warning CS8625: Cannot convert null literal to non-nullable reference type. // A a = new B() { FB = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 30)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Conversions_NullableConversions_01() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F4() where T : struct, I { T? t = new T() { P = 4, Q = null }; // 1 t.Value.P.ToString(); t.Value.Q.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // T? t = new T() { P = 4, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 37), // (12,9): warning CS8602: Dereference of a possibly null reference. // t.Value.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Value.Q").WithLocation(12, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_NullableConversions_02() { var source = @"class C { internal object? F; internal object G = null!; } class Program { static void F() { (C, C)? t = (new C() { F = 1 }, new C() { G = null }); // 1 (((C, C))t).Item1.F.ToString(); (((C, C))t).Item2.G.ToString(); // 2 (C, C)? u = (new C() { F = 2 }, new C() { G = null }); // 3 ((C)u.Value.Item1).F.ToString(); ((C)u.Value.Item2).G.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,55): warning CS8625: Cannot convert null literal to non-nullable reference type. // (C, C)? t = (new C() { F = 1 }, new C() { G = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 55), // (12,9): warning CS8602: Dereference of a possibly null reference. // (((C, C))t).Item2.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((C, C))t).Item2.G").WithLocation(12, 9), // (13,55): warning CS8625: Cannot convert null literal to non-nullable reference type. // (C, C)? u = (new C() { F = 2 }, new C() { G = null }); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 55), // (15,9): warning CS8602: Dereference of a possibly null reference. // ((C)u.Value.Item2).G.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((C)u.Value.Item2).G").WithLocation(15, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Conversions_NullableConversions_03() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { (S, S)? t = (new S() { F = 1 }, new S() { G = null }); // 1 (((S, S))t).Item1.F.ToString(); (((S, S))t).Item2.G.ToString(); // 2 (S, S)? u = (new S() { F = 2 }, new S() { G = null }); // 3 ((S)u.Value.Item1).F.ToString(); ((S)u.Value.Item2).G.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,55): warning CS8625: Cannot convert null literal to non-nullable reference type. // (S, S)? t = (new S() { F = 1 }, new S() { G = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 55), // (12,9): warning CS8602: Dereference of a possibly null reference. // (((S, S))t).Item2.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((S, S))t).Item2.G").WithLocation(12, 9), // (13,55): warning CS8625: Cannot convert null literal to non-nullable reference type. // (S, S)? u = (new S() { F = 2 }, new S() { G = null }); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 55), // (15,9): warning CS8602: Dereference of a possibly null reference. // ((S)u.Value.Item2).G.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((S)u.Value.Item2).G").WithLocation(15, 9)); } [Fact] public void Conversions_NullableConversions_04() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F1(string x1) { S y1 = new S() { F = 1, G = null }; // 1 (object, S)? t1 = (x1, y1); t1.Value.Item2.F.ToString(); t1.Value.Item2.G.ToString(); // 2 } static void F2(string x2) { S y2 = new S() { F = 1, G = null }; // 3 var t2 = ((object, S)?)(x2, y2); t2.Value.Item2.F.ToString(); t2.Value.Item2.G.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S y1 = new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 37), // (13,9): warning CS8602: Dereference of a possibly null reference. // t1.Value.Item2.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1.Value.Item2.G").WithLocation(13, 9), // (17,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S y2 = new S() { F = 1, G = null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(17, 37), // (20,9): warning CS8602: Dereference of a possibly null reference. // t2.Value.Item2.G.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2.Value.Item2.G").WithLocation(20, 9)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void Conversions_NullableConversions_05() { var source = @"struct S { internal object? P { get; set; } internal object Q { get; set; } } class Program { static void Main() { S? s = new S() { P = 1, Q = null }; // 1 s.Value.P.ToString(); s.Value.Q.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S? s = new S() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 37), // (12,9): warning CS8602: Dereference of a possibly null reference. // s.Value.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.Value.Q").WithLocation(12, 9)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void Conversions_NullableConversions_06() { var source = @"struct S { private object? _p; private object _q; internal object? P { get { return _p; } set { _p = value; } } internal object Q { get { return _q; } set { _q = value; } } } class Program { static void Main() { S? s = new S() { P = 1, Q = null }; // 1 s.Value.P.ToString(); s.Value.Q.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S? s = new S() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 37), // (14,9): warning CS8602: Dereference of a possibly null reference. // s.Value.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.Value.Q").WithLocation(14, 9)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void Conversions_NullableConversions_07() { var source = @"struct S { internal object? P { get { return 1; } set { } } internal object Q { get { return 2; } set { } } } class Program { static void Main() { S? s = new S() { P = 1, Q = null }; // 1 s.Value.P.ToString(); s.Value.Q.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // S? s = new S() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 37), // (12,9): warning CS8602: Dereference of a possibly null reference. // s.Value.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.Value.Q").WithLocation(12, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_TupleConversions_01() { var source = @"class A { internal object? FA; } class B : A { internal object FB = new object(); } class Program { static void F() { (B, object) t = (new B() { FA = 1 }, new B() { FB = null }); // 1 t.Item1.FA.ToString(); ((A)t.Item1).FA.ToString(); ((B)t.Item2).FB.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,61): warning CS8625: Cannot convert null literal to non-nullable reference type. // (B, object) t = (new B() { FA = 1 }, new B() { FB = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 61), // (16,9): warning CS8602: Dereference of a possibly null reference. // ((B)t.Item2).FB.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((B)t.Item2).FB").WithLocation(16, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_TupleConversions_02() { var source = @"class A { internal object? FA; } class B : A { internal object FB = new object(); } class Program { static void F() { (B, object) t = (new B() { FA = 1 }, new B() { FB = null }); // 1 (((A, A))t).Item1.FA.ToString(); (((B, B))t).Item2.FB.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,61): warning CS8625: Cannot convert null literal to non-nullable reference type. // (B, object) t = (new B() { FA = 1 }, new B() { FB = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 61), // (15,9): warning CS8602: Dereference of a possibly null reference. // (((B, B))t).Item2.FB.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((B, B))t).Item2.FB").WithLocation(15, 9)); } [Fact] [WorkItem(29977, "https://github.com/dotnet/roslyn/issues/29977")] public void Conversions_TupleConversions_03() { var source = @"class A { internal object? FA; } class B : A { internal object FB = new object(); } class Program { static void F() { B b = new B() { FA = 1, FB = null }; // 1 (B, (A, A)) t; t = (b, (b, b)); t.Item1.FB.ToString(); // 2 t.Item2.Item1.FA.ToString(); t = ((B, (A, A)))(b, (b, b)); t.Item1.FB.ToString(); // 3 t.Item2.Item1.FA.ToString(); (A, (B, B)) u; u = t; // 4 u.Item1.FA.ToString(); u.Item2.Item2.FB.ToString(); // 5 u = ((A, (B, B)))t; u.Item1.FA.ToString(); u.Item2.Item2.FB.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,38): warning CS8625: Cannot convert null literal to non-nullable reference type. // B b = new B() { FA = 1, FB = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 38), // (16,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.FB.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.FB").WithLocation(16, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.FB.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1.FB").WithLocation(19, 9), // (22,13): error CS0266: Cannot implicitly convert type '(B, (A, A))' to '(A, (B, B))'. An explicit conversion exists (are you missing a cast?) // u = t; // 4 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "t").WithArguments("(B, (A, A))", "(A, (B, B))").WithLocation(22, 13), // (24,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.Item2.FB.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2.Item2.FB").WithLocation(24, 9), // (27,9): warning CS8602: Dereference of a possibly null reference. // u.Item2.Item2.FB.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2.Item2.FB").WithLocation(27, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(34086, "https://github.com/dotnet/roslyn/issues/34086")] public void Conversions_TupleConversions_04() { var source = @"class C { internal object? F; } class Program { static void F() { (object, object)? t = (new C() { F = 1 }, new object()); (((C, object))t).Item1.F.ToString(); (object, object)? u = (new C() { F = 2 }, new object()); ((C)u.Value.Item1).F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/34086: Track state across Nullable conversions with nested conversions. comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // (((C, object))t).Item1.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((C, object))t).Item1.F").WithLocation(10, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(34086, "https://github.com/dotnet/roslyn/issues/34086")] public void Conversions_TupleConversions_05() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { (S?, object?) t = (new S() { F = 1 }, new S() { G = null }); // 1 (((S, S))t).Item1.F.ToString(); (((S, S))t).Item2.G.ToString(); // 2 (S?, object?) u = (new S() { F = 2 }, new S() { G = null }); // 3 u.Item1.Value.F.ToString(); ((S?)u.Item2).Value.G.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/34086: Track state across Nullable conversions with nested conversions. comp.VerifyDiagnostics( // (10,61): warning CS8625: Cannot convert null literal to non-nullable reference type. // (S?, object?) t = (new S() { F = 1 }, new S() { G = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 61), // (11,9): warning CS8602: Dereference of a possibly null reference. // (((S, S))t).Item1.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((S, S))t).Item1.F").WithLocation(11, 9), // (11,10): warning CS8619: Nullability of reference types in value of type '(S?, object?)' doesn't match target type '(S, S)'. // (((S, S))t).Item1.F.ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((S, S))t").WithArguments("(S?, object?)", "(S, S)").WithLocation(11, 10), // (12,9): warning CS8602: Possible dereference of a null reference. // (((S, S))t).Item2.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((S, S))t).Item2.G").WithLocation(12, 9), // (12,10): warning CS8619: Nullability of reference types in value of type '(S?, object?)' doesn't match target type '(S, S)'. // (((S, S))t).Item2.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((S, S))t").WithArguments("(S?, object?)", "(S, S)").WithLocation(12, 10), // (13,61): warning CS8625: Cannot convert null literal to non-nullable reference type. // (S?, object?) u = (new S() { F = 2 }, new S() { G = null }); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 61)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Conversions_TupleConversions_06() { var source = @"class Program { static void F1((object?, object) t1) { var u1 = ((string, string))t1; // 1 u1.Item1.ToString(); // 2 u1.Item1.ToString(); } static void F2((object?, object) t2) { var u2 = ((string?, string?))t2; u2.Item1.ToString(); // 3 u2.Item2.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,18): warning CS8619: Nullability of reference types in value of type '(object?, object)' doesn't match target type '(string, string)'. // var u1 = ((string, string))t1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((string, string))t1").WithArguments("(object?, object)", "(string, string)").WithLocation(5, 18), // (6,9): warning CS8602: Dereference of a possibly null reference. // u1.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u1.Item1").WithLocation(6, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // u2.Item1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2.Item1").WithLocation(12, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Conversions_TupleConversions_07() { var source = @"class A { public static implicit operator B?(A a) => null; } class B { } class Program { static void F(A a, B b) { (B, B) t = (a, b); // 1 t.Item1.ToString(); // 2 t.Item2.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,20): warning CS8619: Nullability of reference types in value of type '(B? a, B b)' doesn't match target type '(B, B)'. // (B, B) t = (a, b); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(a, b)").WithArguments("(B? a, B b)", "(B, B)").WithLocation(12, 20), // (13,9): warning CS8602: Possible dereference of a null reference. // t.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(13, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] public void Conversions_TupleConversions_08() { var source = @"class A { public static implicit operator B?(A a) => null; } class B { } class Program { static void F(A a, B b) { var t = ((B, B))(b, a); // 1, 2 t.Item1.ToString(); t.Item2.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,17): warning CS8619: Nullability of reference types in value of type '(B b, B? a)' doesn't match target type '(B, B)'. // var t = ((B, B))(b, a); // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((B, B))(b, a)").WithArguments("(B b, B? a)", "(B, B)").WithLocation(12, 17), // (12,29): warning CS8600: Converting null literal or possible null value to non-nullable type. // var t = ((B, B))(b, a); // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "a").WithLocation(12, 29), // (14,9): warning CS8602: Possible dereference of a null reference. // t.Item2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(14, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_09() { var source = @"class A { public static implicit operator B?(A a) => null; } class B { } struct S { internal object? F; } class Program { static void F1() { (B, S) t1 = (new A(), new S() { F = 1 }); // 1 t1.Item1.ToString(); // 2 t1.Item2.F.ToString(); } static void F2() { (A, S?) t2 = (new A(), new S() { F = 2 }); t2.Item1.ToString(); t2.Item2.Value.F.ToString(); } static void F3() { (B, S?) t3 = (new A(), new S() { F = 3 }); // 3 t3.Item1.ToString(); // 4 t3.Item2.Value.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,21): warning CS8619: Nullability of reference types in value of type '(B?, S)' doesn't match target type '(B, S)'. // (B, S) t1 = (new A(), new S() { F = 1 }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(new A(), new S() { F = 1 })").WithArguments("(B?, S)", "(B, S)").WithLocation(16, 21), // (17,9): warning CS8602: Possible dereference of a null reference. // t1.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1.Item1").WithLocation(17, 9), // (28,22): warning CS8619: Nullability of reference types in value of type '(B?, S?)' doesn't match target type '(B, S?)'. // (B, S?) t3 = (new A(), new S() { F = 3 }); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(new A(), new S() { F = 3 })").WithArguments("(B?, S?)", "(B, S?)").WithLocation(28, 22), // (29,9): warning CS8602: Possible dereference of a null reference. // t3.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3.Item1").WithLocation(29, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_10() { var source = @"class A { public static implicit operator B?(A a) => null; } class B { } struct S { internal object? F; } class Program { static void F1() { var t1 = ((S, B))(new S() { F = 1 }, new A()); // 1, 2 t1.Item1.F.ToString(); t1.Item2.ToString(); // 3 } static void F2() { var t2 = ((S?, A))(new S() { F = 2 }, new A()); t2.Item1.Value.F.ToString(); t2.Item2.ToString(); } static void F3() { var t3 = ((S?, B))(new S() { F = 3 }, new A()); // 4, 5 t3.Item1.Value.F.ToString(); t3.Item2.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,18): warning CS8619: Nullability of reference types in value of type '(S, B?)' doesn't match target type '(S, B)'. // var t1 = ((S, B))(new S() { F = 1 }, new A()); // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((S, B))(new S() { F = 1 }, new A())").WithArguments("(S, B?)", "(S, B)").WithLocation(16, 18), // (16,46): warning CS8600: Converting null literal or possible null value to non-nullable type. // var t1 = ((S, B))(new S() { F = 1 }, new A()); // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "new A()").WithLocation(16, 46), // (18,9): warning CS8602: Possible dereference of a null reference. // t1.Item2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1.Item2").WithLocation(18, 9), // (28,18): warning CS8619: Nullability of reference types in value of type '(S?, B?)' doesn't match target type '(S?, B)'. // var t3 = ((S?, B))(new S() { F = 3 }, new A()); // 4, 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((S?, B))(new S() { F = 3 }, new A())").WithArguments("(S?, B?)", "(S?, B)").WithLocation(28, 18), // (28,47): warning CS8600: Converting null literal or possible null value to non-nullable type. // var t3 = ((S?, B))(new S() { F = 3 }, new A()); // 4, 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "new A()").WithLocation(28, 47), // (30,9): warning CS8602: Possible dereference of a null reference. // t3.Item2.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3.Item2").WithLocation(30, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_11() { var source = @"class A { public static implicit operator B?(A a) => null; } class B { } struct S { internal object? F; } class Program { static void F1() { (A, S) t1 = (new A(), new S() { F = 1 }); (B, S?) u1 = t1; // 1 u1.Item1.ToString(); // 2 u1.Item2.Value.F.ToString(); } static void F2() { (A, S) t2 = (new A(), new S() { F = 2 }); var u2 = ((B, S?))t2; // 3 u2.Item1.ToString(); // 4 u2.Item2.Value.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/34495: Improve warning message to reference user-defined conversion and t1.Item1 or t2.Item1. comp.VerifyDiagnostics( // (17,22): warning CS8601: Possible null reference assignment. // (B, S?) u1 = t1; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t1").WithLocation(17, 22), // (18,9): warning CS8602: Possible dereference of a null reference. // u1.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u1.Item1").WithLocation(18, 9), // (24,18): warning CS8601: Possible null reference assignment. // var u2 = ((B, S?))t2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "((B, S?))t2").WithLocation(24, 18), // (25,9): warning CS8602: Possible dereference of a null reference. // u2.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2.Item1").WithLocation(25, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_12() { var source = @"#pragma warning disable 0649 class A { public static implicit operator B?(A a) => null; } class B { } struct S { internal object? F; } class Program { static void F1() { (int, (A, S)) t1 = (1, (new A(), new S() { F = 1 })); (object x, (B, S?) y) u1 = t1; // 1 u1.y.Item1.ToString(); // 2 u1.y.Item2.Value.F.ToString(); } static void F2() { (int, (A, S)) t2 = (2, (new A(), new S() { F = 2 })); var u2 = ((object x, (B, S?) y))t2; // 3 u2.y.Item1.ToString(); // 4 u2.y.Item2.Value.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/34495: Improve warning message to reference user-defined conversion and t1.Item2.Item1 or t2.Item2.Item1. comp.VerifyDiagnostics( // (18,36): warning CS8601: Possible null reference assignment. // (object x, (B, S?) y) u1 = t1; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t1").WithLocation(18, 36), // (19,9): warning CS8602: Possible dereference of a null reference. // u1.y.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u1.y.Item1").WithLocation(19, 9), // (25,18): warning CS8601: Possible null reference assignment. // var u2 = ((object x, (B, S?) y))t2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "((object x, (B, S?) y))t2").WithLocation(25, 18), // (26,9): warning CS8602: Possible dereference of a null reference. // u2.y.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2.y.Item1").WithLocation(26, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_13() { var source = @"class A { public static implicit operator B(A a) => throw null!; } class B { } struct S { internal object? F; internal object G; } class Program { static void F() { A x = new A(); S y = new S() { F = 1, G = null }; // 1 var t = (x, y, x, y, x, y, x, y, x, y); (B?, S?, B?, S?, B?, S?, B?, S?, B?, S?) u = t; u.Item1.ToString(); u.Item2.Value.F.ToString(); u.Item2.Value.G.ToString(); // 2 u.Item9.ToString(); u.Item10.Value.F.ToString(); u.Item10.Value.G.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,36): warning CS8625: Cannot convert null literal to non-nullable reference type. // S y = new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(18, 36), // (23,9): warning CS8602: Possible dereference of a null reference. // u.Item2.Value.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item2.Value.G").WithLocation(23, 9), // (26,9): warning CS8602: Possible dereference of a null reference. // u.Item10.Value.G.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.Item10.Value.G").WithLocation(26, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_14() { var source = @"class A { public static implicit operator A?(int i) => new A(); } class B { public static implicit operator B(int i) => new B(); } class Program { static void F1((int, int) t1) { (A, B?) u1 = t1; // 1 u1.Item1.ToString(); // 2 u1.Item2.ToString(); } static void F2((int, int) t2) { var u2 = ((B?, A))t2; // 3 u2.Item1.ToString(); // 4 u2.Item2.ToString(); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/34495: Improve warning message to reference user-defined conversion and t1.Item2 or t2.Item1. comp.VerifyDiagnostics( // (13,22): warning CS8601: Possible null reference assignment. // (A, B?) u1 = t1; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t1").WithLocation(13, 22), // (14,9): warning CS8602: Dereference of a possibly null reference. // u1.Item1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u1.Item1").WithLocation(14, 9), // (19,18): warning CS8601: Possible null reference assignment. // var u2 = ((B?, A))t2; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "((B?, A))t2").WithLocation(19, 18), // (20,9): warning CS8602: Dereference of a possibly null reference. // u2.Item1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2.Item1").WithLocation(20, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // u2.Item2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u2.Item2").WithLocation(21, 9)); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_15() { var source = @"class A { public static implicit operator A?(int i) => new A(); } class B { public static implicit operator B(int i) => new B(); } struct S { public static implicit operator S((A, B?) t) => default; } class Program { static void F1((int, int) t) { F2(t); // 1 F3(t); // 2 } static void F2((A, B?) t) { } static void F3(S? s) { } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32599: Handle tuple element conversions. comp.VerifyDiagnostics(); } [Fact] [WorkItem(32599, "https://github.com/dotnet/roslyn/issues/32599")] [WorkItem(32600, "https://github.com/dotnet/roslyn/issues/32600")] public void Conversions_TupleConversions_16() { var source = @"class A { } class B { public static implicit operator B?(A a) => new B(); } struct S { public static implicit operator (A?, A)(S s) => default; } class Program { static void F1(S s) { F2(s); // 1 F3(s); // 2 } static void F2((A, A?)? t) { } static void F3((B?, B) t) { } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32599: Handle tuple element conversions. comp.VerifyDiagnostics( // (16,12): warning CS8620: Argument of type '(A?, A)?' cannot be used for parameter 't' of type '(A, A?)?' in 'void Program.F2((A, A?)? t)' due to differences in the nullability of reference types. // F2(s); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s").WithArguments("(A?, A)?", "(A, A?)?", "t", "void Program.F2((A, A?)? t)").WithLocation(16, 12)); } [Fact] public void Conversions_BoxingConversions_01() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { object o = new S() { F = 1, G = null }; // 1 ((S)o).F.ToString(); ((S)o).G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,41): warning CS8625: Cannot convert null literal to non-nullable reference type. // object o = new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 41), // (12,9): warning CS8602: Dereference of a possibly null reference. // ((S)o).G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((S)o).G").WithLocation(12, 9)); } [Fact] public void Conversions_BoxingConversions_02() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { ((S)(object)new S() { F = 1 }).F.ToString(); ((S)(object)new S() { G = null }).F.ToString(); // 1, 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // ((S)(object)new S() { G = null }).F.ToString(); // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((S)(object)new S() { G = null }).F").WithLocation(11, 9), // (11,35): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((S)(object)new S() { G = null }).F.ToString(); // 1, 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 35)); } [Fact] public void Conversions_BoxingConversions_03() { var source = @"struct S { internal object? F; internal object G; } class Program { static void F() { object? o = (S?)new S() { F = 1, G = null }; // 1 ((S?)o).Value.F.ToString(); ((S?)o).Value.G.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,46): warning CS8625: Cannot convert null literal to non-nullable reference type. // object? o = (S?)new S() { F = 1, G = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 46), // (12,9): warning CS8602: Dereference of a possibly null reference. // ((S?)o).Value.G.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((S?)o).Value.G").WithLocation(12, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Conversions_BoxingConversions_04() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F1() where T : I, new() { object o1 = new T() { P = 1, Q = null }; // 1 ((T)o1).P.ToString(); ((T)o1).Q.ToString(); // 2 } static void F2() where T : class, I, new() { object o2 = new T() { P = 2, Q = null }; // 3 ((T)o2).P.ToString(); ((T)o2).Q.ToString(); // 4 } static void F3() where T : struct, I { object o3 = new T() { P = 3, Q = null }; // 5 ((T)o3).P.ToString(); ((T)o3).Q.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,42): warning CS8625: Cannot convert null literal to non-nullable reference type. // object o1 = new T() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 42), // (12,9): warning CS8602: Dereference of a possibly null reference. // ((T)o1).Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T)o1).Q").WithLocation(12, 9), // (16,42): warning CS8625: Cannot convert null literal to non-nullable reference type. // object o2 = new T() { P = 2, Q = null }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 42), // (18,9): warning CS8602: Dereference of a possibly null reference. // ((T)o2).Q.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T)o2).Q").WithLocation(18, 9), // (22,42): warning CS8625: Cannot convert null literal to non-nullable reference type. // object o3 = new T() { P = 3, Q = null }; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(22, 42), // (24,9): warning CS8602: Dereference of a possibly null reference. // ((T)o3).Q.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T)o3).Q").WithLocation(24, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Conversions_BoxingConversions_05() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F1() where T1 : I, new() { ((T1)(object)new T1() { P = 1 }).P.ToString(); ((T1)(object)new T1() { Q = null }).Q.ToString(); // 1, 2 } static void F2() where T2 : class, I, new() { ((T2)(object)new T2() { P = 2 }).P.ToString(); ((T2)(object)new T2() { Q = null }).Q.ToString(); // 3, 4 } static void F3() where T3 : struct, I { ((T3)(object)new T3() { P = 3 }).P.ToString(); ((T3)(object)new T3() { Q = null }).Q.ToString(); // 5, 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // ((T1)(object)new T1() { Q = null }).Q.ToString(); // 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T1)(object)new T1() { Q = null }).Q").WithLocation(11, 9), // (11,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((T1)(object)new T1() { Q = null }).Q.ToString(); // 1, 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 37), // (16,9): warning CS8602: Dereference of a possibly null reference. // ((T2)(object)new T2() { Q = null }).Q.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T2)(object)new T2() { Q = null }).Q").WithLocation(16, 9), // (16,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((T2)(object)new T2() { Q = null }).Q.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 37), // (21,9): warning CS8602: Dereference of a possibly null reference. // ((T3)(object)new T3() { Q = null }).Q.ToString(); // 5, 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T3)(object)new T3() { Q = null }).Q").WithLocation(21, 9), // (21,37): warning CS8625: Cannot convert null literal to non-nullable reference type. // ((T3)(object)new T3() { Q = null }).Q.ToString(); // 5, 6 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(21, 37)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Conversions_BoxingConversions_06() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F1() where T : I, new() { (object, object) t1 = (new T() { P = 1 }, new T() { Q = null }); // 1 ((T)t1.Item1).P.ToString(); (((T, T))t1).Item2.Q.ToString(); // 2 } static void F2() where T : class, I, new() { (object, object) t2 = (new T() { P = 2 }, new T() { Q = null }); // 3 ((T)t2.Item1).P.ToString(); (((T, T))t2).Item2.Q.ToString(); // 4 } static void F3() where T : struct, I { (object, object) t3 = (new T() { P = 3 }, new T() { Q = null }); // 5 ((T)t3.Item1).P.ToString(); (((T, T))t3).Item2.Q.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,65): warning CS8625: Cannot convert null literal to non-nullable reference type. // (object, object) t1 = (new T() { P = 1 }, new T() { Q = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 65), // (12,9): warning CS8602: Dereference of a possibly null reference. // (((T, T))t1).Item2.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((T, T))t1).Item2.Q").WithLocation(12, 9), // (16,65): warning CS8625: Cannot convert null literal to non-nullable reference type. // (object, object) t2 = (new T() { P = 2 }, new T() { Q = null }); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 65), // (18,9): warning CS8602: Dereference of a possibly null reference. // (((T, T))t2).Item2.Q.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((T, T))t2).Item2.Q").WithLocation(18, 9), // (22,65): warning CS8625: Cannot convert null literal to non-nullable reference type. // (object, object) t3 = (new T() { P = 3 }, new T() { Q = null }); // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(22, 65), // (24,9): warning CS8602: Dereference of a possibly null reference. // (((T, T))t3).Item2.Q.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((T, T))t3).Item2.Q").WithLocation(24, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Conversions_BoxingConversions_07() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F() where T : struct, I { object o = (T?)new T() { P = 1, Q = null }; // 1 ((T?)o).Value.P.ToString(); ((T?)o).Value.Q.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,45): warning CS8625: Cannot convert null literal to non-nullable reference type. // object o = (T?)new T() { P = 1, Q = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 45), // (12,9): warning CS8602: Dereference of a possibly null reference. // ((T?)o).Value.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "((T?)o).Value.Q").WithLocation(12, 9)); } [Fact] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] [WorkItem(34086, "https://github.com/dotnet/roslyn/issues/34086")] public void Conversions_BoxingConversions_08() { var source = @"interface I { object? P { get; set; } object Q { get; set; } } class Program { static void F() where T : struct, I { (object, object) t = ((T?, T?))(new T() { P = 1 }, new T() { Q = null }); // 1 ((T?)t.Item1).Value.P.ToString(); (((T?, T?))t).Item2.Value.Q.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,30): warning CS8619: Nullability of reference types in value of type '(T?, T?)' doesn't match target type '(object, object)'. // (object, object) t = ((T?, T?))(new T() { P = 1 }, new T() { Q = null }); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "((T?, T?))(new T() { P = 1 }, new T() { Q = null })").WithArguments("(T?, T?)", "(object, object)").WithLocation(10, 30), // (10,74): warning CS8625: Cannot convert null literal to non-nullable reference type. // (object, object) t = ((T?, T?))(new T() { P = 1 }, new T() { Q = null }); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 74), // (12,9): warning CS8602: Possible dereference of a null reference. // (((T?, T?))t).Item2.Value.Q.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(((T?, T?))t).Item2.Value.Q").WithLocation(12, 9)); } [Fact] public void Members_FieldCycle_01() { var source = @"class C { C? F; void M() { F = this; F.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // F.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F.F").WithLocation(7, 9)); } [Fact] public void Members_FieldCycle_02() { var source = @"class C { C? F; void M() { F = new C() { F = this }; F.F.ToString(); F.F.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // F.F.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F.F.F").WithLocation(8, 9)); } [Fact] public void Members_FieldCycle_03() { var source = @"class C { C? F; static void M() { var x = new C(); x.F = x; var y = new C() { F = x }; y.F.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Members_FieldCycle_04() { var source = @"class C { C? F; static void M(C x) { object? y = x; for (int i = 0; i < 3; i++) { x.F = x; y = null; } x.F.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // x.F.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(12, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // x.F.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F.F").WithLocation(12, 9)); } [Fact] public void Members_FieldCycle_05() { var source = @"class C { C? F; static void M(C x) { (x.F, _) = (x, 0); x.F.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x.F.F.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F.F").WithLocation(7, 9)); } [Fact] public void Members_FieldCycle_06() { var source = @"#pragma warning disable 0649 class A { internal B B = default!; } class B { internal A? A; } class Program { static void M(A a) { a.B.A = a; a.B.A.B.A.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // a.B.A.B.A.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.B.A.B.A").WithLocation(15, 9)); } [Fact] [WorkItem(33908, "https://github.com/dotnet/roslyn/issues/33908")] public void Members_FieldCycle_07() { var source = @"#pragma warning disable 8618 class C { C F; static void M() { C x = null; while (true) { C y = new C() { F = x }; x = y; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,7): warning CS0414: The field 'C.F' is assigned but its value is never used // C F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("C.F").WithLocation(4, 7), // (7,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // C x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 15), // (10,33): warning CS8601: Possible null reference assignment. // C y = new C() { F = x }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(10, 33)); } [Fact] [WorkItem(33908, "https://github.com/dotnet/roslyn/issues/33908")] public void Members_FieldCycle_08() { var source = @"#pragma warning disable 8618 class C { C F; static void M() { C x = null; while (true) { C y = new C() { F = x }; x = new C() { F = y }; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,7): warning CS0414: The field 'C.F' is assigned but its value is never used // C F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("C.F").WithLocation(4, 7), // (7,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // C x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 15), // (10,33): warning CS8601: Possible null reference assignment. // C y = new C() { F = x }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(10, 33)); } [Fact] [WorkItem(33908, "https://github.com/dotnet/roslyn/issues/33908")] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Members_FieldCycle_09() { var source = @"#pragma warning disable 8618 class C { internal T F; } class Program { static void F() where T : C, new() { T x = default; while (true) { T y = new T() { F = x }; x = y; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x = default; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(10, 15), // (13,33): warning CS8601: Possible null reference assignment. // T y = new T() { F = x }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(13, 33)); } [Fact] [WorkItem(33908, "https://github.com/dotnet/roslyn/issues/33908")] [WorkItem(33387, "https://github.com/dotnet/roslyn/issues/33387")] public void Members_FieldCycle_10() { var source = @"interface I { T P { get; set; } } class Program { static void F1() where T : I, new() { T x1 = default; while (true) { T y1 = new T() { P = x1 }; x1 = y1; } } static void F2() where T : class, I, new() { T x2 = default; while (true) { T y2 = new T() { P = x2 }; x2 = y2; } } static void F3() where T : struct, I { T x3 = default; while (true) { T y3 = new T() { P = x3 }; x3 = y3; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,16): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // T x1 = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(9, 16), // (18,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x2 = default; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(18, 16), // (21,34): warning CS8601: Possible null reference assignment. // T y2 = new T() { P = x2 }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x2").WithLocation(21, 34)); } [Fact] public void Members_FieldCycle_Struct() { var source = @"struct S { internal C F; internal C? G; } class C { internal S S; static void Main() { var s = new S() { F = new C(), G = new C() }; s.F.S = s; s.G.S = s; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } // Valid struct since the property is not backed by a field. [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void Members_PropertyCycle_Struct() { var source = @"#pragma warning disable 0649 struct S { internal S(object? f) { F = f; } internal object? F; internal S P { get { return new S(F); } set { F = value.F; } } } class C { static void M(S s) { s.P.F.ToString(); // 1 if (s.P.F == null) return; s.P.F.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // s.P.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.P.F").WithLocation(19, 9)); } [Fact] [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")] public void Members_StructProperty_Default() { var source = @"#pragma warning disable 0649 struct S { internal object F; private object _p; internal object P { get { return _p; } set { _p = value; } } internal object Q { get; set; } } class Program { static void Main() { S s = default; s.F.ToString(); // 1 s.P.ToString(); s.Q.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // s.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s.F").WithLocation(14, 9)); } [Fact] public void Members_StaticField_Struct() { var source = @"struct S where T : class { internal T F; internal T? G; internal static S Instance = new S(); } class Program { static void F() where T : class, new() { S.Instance.F = null; // 1 S.Instance.G = new T(); S.Instance.F.ToString(); // 2 S.Instance.G.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,27): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter. // S.Instance.F = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 27), // (13,9): warning CS8602: Dereference of a possibly null reference. // S.Instance.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.Instance.F").WithLocation(13, 9)); } [Fact] public void Members_DefaultConstructor_Class() { var source = @"#pragma warning disable 649 #pragma warning disable 8618 class A { internal object? A1; internal object A2; } class B { internal B() { B2 = null!; } internal object? B1; internal object B2; } class Program { static void Main() { A a = new A(); a.A1.ToString(); // 1 a.A2.ToString(); B b = new B(); b.B1.ToString(); // 2 b.B2.ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (22,9): warning CS8602: Dereference of a possibly null reference. // a.A1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.A1").WithLocation(22, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // b.B1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.B1").WithLocation(25, 9)); } [Fact] public void SelectAnonymousType() { var source = @"using System.Collections.Generic; using System.Linq; class C { int? E; static void F(IEnumerable c) { const int F = 0; c.Select(o => new { E = o.E ?? F }); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,10): warning CS0649: Field 'C.E' is never assigned to, and will always have its default value // int? E; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "E").WithArguments("C.E", "").WithLocation(5, 10)); } [Fact] public void Constraints_01() { var source = @"interface I { T P { get; set; } } class A { } class B { static void F1(T t1) where T : A { t1.ToString(); t1 = default; // 1 } static void F2(T t2) where T : A? { t2.ToString(); // 2 t2 = default; // 3 } static void F3(T t3) where T : I { t3.P.ToString(); t3 = default; // 6 } static void F4(T t4) where T : I? { t4.P.ToString(); // 7 and 8 t4.P = default; // 9 t4 = default; // 10 } static void F5(T t5) where T : I { t5.P.ToString(); // 11 and 12 t5.P = default; t5 = default; // 15 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29978: Various differences from expected warnings. comp.VerifyDiagnostics( // (29,41): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void F5(T t5) where T : I Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(29, 41), // (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // t1 = default; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(11, 14), // (15,9): warning CS8602: Dereference of a possibly null reference. // t2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(15, 9), // (16,14): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // t2 = default; // 3 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(16, 14), // (21,14): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // t3 = default; // 6 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(21, 14), // (25,9): warning CS8602: Dereference of a possibly null reference. // t4.P.ToString(); // 7 and 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4").WithLocation(25, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // t4.P.ToString(); // 7 and 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4.P").WithLocation(25, 9), // (26,16): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // t4.P = default; // 9 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(26, 16), // (27,14): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // t4 = default; // 10 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(27, 14), // (31,9): warning CS8602: Dereference of a possibly null reference. // t5.P.ToString(); // 11 and 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5.P").WithLocation(31, 9), // (33,14): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // t5 = default; // 15 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(33, 14) ); } [Fact] public void Constraints_02() { var source = @" class B { public static void F1(T1? t1) where T1 : class { } public static void F2(T2 t2) where T2 : class? { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var b = m.GlobalNamespace.GetMember("B"); if (isSource) { Assert.Empty(b.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", b.GetAttributes().First().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : class!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.ReferenceTypeConstraintIsNullable); Assert.Empty(t1.GetAttributes()); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T2 t2) where T2 : class?", f2.ToDisplayString(SymbolDisplayFormat.TestFormat.WithGenericsOptions(SymbolDisplayFormat.TestFormat.GenericsOptions | SymbolDisplayGenericsOptions.IncludeTypeConstraints))); Assert.Equal("void B.F2(T2 t2) where T2 : class", f2.ToDisplayString(SymbolDisplayFormat.TestFormat.WithGenericsOptions(SymbolDisplayFormat.TestFormat.GenericsOptions | SymbolDisplayGenericsOptions.IncludeTypeConstraints). WithMiscellaneousOptions(SymbolDisplayFormat.TestFormatWithConstraints.MiscellaneousOptions & (~SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier)))); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t2.GetAttributes().Single().ToString()); } } } [Fact] public void Constraints_03() { var source = @" class A where T1 : class { public static void F1(T1? t1) { } } class B where T2 : class? { public static void F2(T2 t2) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var a = (NamedTypeSymbol)m.GlobalNamespace.GetMember("A"); Assert.Equal("A where T1 : class!", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = a.TypeParameters[0]; Assert.False(t1.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(1)", t1.GetAttributes().Single().ToString()); } var b = (NamedTypeSymbol)m.GlobalNamespace.GetMember("B"); Assert.Equal("B where T2 : class?", b.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = b.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t2.GetAttributes().Single().ToString()); } } } [Fact] public void Constraints_04() { var source = @" #pragma warning disable CS8321 class B { public static void Test() { void F1(T1? t1) where T1 : class { } void F2(T2 t2) where T2 : class? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var localSyntaxes = tree.GetRoot().DescendantNodes().OfType().ToArray(); Assert.Equal(2, localSyntaxes.Length); var f1 = (LocalFunctionSymbol)model.GetDeclaredSymbol(localSyntaxes[0]); Assert.Equal("void F1(T1? t1) where T1 : class!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.ReferenceTypeConstraintIsNullable); Assert.Empty(t1.GetAttributes()); var f2 = (LocalFunctionSymbol)model.GetDeclaredSymbol(localSyntaxes[1]); Assert.Equal("void F2(T2 t2) where T2 : class?", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); Assert.Empty(t2.GetAttributes()); } [Fact] public void Constraints_05() { var source = @" #pragma warning disable CS8321 class B where T1 : class? { public static void F2(T2 t2) where T2 : class? { void F3(T3 t3) where T3 : class? { } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (4,29): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B where T1 : class? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 29), // (6,54): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static void F2(T2 t2) where T2 : class? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(6, 54), // (8,44): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void F3(T3 t3) where T3 : class? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 44) ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var b = (NamedTypeSymbol)m.GlobalNamespace.GetMember("B"); Assert.Equal("B where T1 : class?", b.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = b.TypeParameters[0]; Assert.True(t1.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t1.GetAttributes().Single().ToString()); } var f2 = (MethodSymbol)b.GetMember("F2"); Assert.Equal("void B.F2(T2 t2) where T2 : class?", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t2.GetAttributes().Single().ToString()); } } comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); var expected = new[] { // (4,29): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // class B where T1 : class? Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(4, 29), // (6,54): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // public static void F2(T2 t2) where T2 : class? Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(6, 54), // (8,44): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // void F3(T3 t3) where T3 : class? Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(8, 44) }; comp.VerifyDiagnostics(expected); comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.RegularDefault, skipUsesIsNullable: true); comp.VerifyDiagnostics(expected); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); comp.VerifyDiagnostics(expected .Concat(new[] { // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.3", "preview").WithLocation(1, 1), }).ToArray() ); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.RegularDefault, skipUsesIsNullable: true); comp.VerifyDiagnostics(expected .Concat(new[] { // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.3", "preview").WithLocation(1, 1), }).ToArray() ); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); comp.VerifyDiagnostics(); } [Fact] public void Constraints_06() { var source = @" #pragma warning disable CS8321 class B where T1 : class? { public static void F1(T1? t1) {} public static void F2(T2? t2) where T2 : class? { void F3(T3? t3) where T3 : class? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,31): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F2(T2? t2) where T2 : class? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(9, 31), // (6,27): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F1(T1? t1) Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T1?").WithLocation(6, 27), // (11,21): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F3(T3? t3) where T3 : class? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T3?").WithLocation(11, 21) ); } [Fact] public void Constraints_07() { var source = @" class B { public static void F1(T12? t1) where T11 : class where T12 : T11 {} public static void F2(T22? t1) where T21 : class where T22 : class, T21 {} public static void F3(T32? t1) where T31 : B where T32 : T31 {} public static void F4(T42? t1) where T41 : B where T42 : T41? {} }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,37): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F1(T12? t1) where T11 : class where T12 : T11 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T12?").WithLocation(4, 37), // (13,37): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F4(T42? t1) where T41 : B where T42 : T41? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T42?").WithLocation(13, 37) ); } [Fact] public void Constraints_08() { var source = @" #pragma warning disable CS8321 class B where T12 : T11? { public static void F2() where T22 : T21? { void F3() where T32 : T31? { } } public static void F4() where T4 : T4? {} }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,31): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class B where T12 : T11? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T11?").WithLocation(4, 31), // (6,51): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F2() where T22 : T21? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T21?").WithLocation(6, 51), // (8,41): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F3() where T32 : T31? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T31?").WithLocation(8, 41), // (13,27): error CS0454: Circular constraint dependency involving 'T4' and 'T4' // public static void F4() where T4 : T4? Diagnostic(ErrorCode.ERR_CircularConstraint, "T4").WithArguments("T4", "T4").WithLocation(13, 27), // (13,44): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F4() where T4 : T4? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T4?").WithLocation(13, 44) ); } [Fact] public void Constraints_09() { var source = @" class B { public static void F1() where T1 : Node? {} public static void F2() where T2 : Node {} public static void F3() where T3 : Node? {} } class Node {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,49): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3() where T3 : Node? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T3?").WithLocation(10, 49) ); } [Fact] public void Constraints_10() { var source = @" class B { public static void F1() where T1 : class, Node? {} public static void F2() where T2 : class, Node {} public static void F3() where T3 : class, Node? {} } class Node {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,51): error CS0450: 'Node': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F2() where T2 : class, Node Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "Node").WithArguments("Node").WithLocation(7, 51), // (10,51): error CS0450: 'Node': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F3() where T3 : class, Node? Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "Node?").WithArguments("Node").WithLocation(10, 51), // (4,51): error CS0450: 'Node': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F1() where T1 : class, Node? Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "Node?").WithArguments("Node").WithLocation(4, 51) ); } [Fact] public void Constraints_11() { var source = @" class B { public static void F1() where T1 : class?, Node? {} public static void F2() where T2 : class?, Node {} public static void F3() where T3 : class?, Node? {} } class Node {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,52): error CS0450: 'Node': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F2() where T2 : class?, Node Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "Node").WithArguments("Node").WithLocation(7, 52), // (7,57): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F2() where T2 : class?, Node Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(7, 57), // (10,52): error CS0450: 'Node': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F3() where T3 : class?, Node? Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "Node?").WithArguments("Node").WithLocation(10, 52), // (10,57): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3() where T3 : class?, Node? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T3?").WithLocation(10, 57), // (4,52): error CS0450: 'Node': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F1() where T1 : class?, Node? Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "Node?").WithArguments("Node").WithLocation(4, 52) ); } [Fact] public void Constraints_12() { var source = @" class B { public static void F1() where T1 : INode? {} public static void F2() where T2 : INode {} public static void F3() where T3 : INode? {} } interface INode {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,50): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F2() where T2 : INode Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(7, 50), // (10,50): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3() where T3 : INode? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T3?").WithLocation(10, 50) ); } [Fact] public void Constraints_13() { var source = @" class B { public static void F1() where T1 : class, INode? {} public static void F2() where T2 : class, INode {} public static void F3() where T3 : class, INode? {} } interface INode {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); } [Fact] public void Constraints_14() { var source = @" class B { public static void F1() where T1 : class?, INode? {} public static void F2() where T2 : class?, INode {} public static void F3() where T3 : class?, INode? {} } interface INode {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,58): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3() where T3 : class?, INode? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T3?").WithLocation(10, 58) ); } [Fact] public void Constraints_15() { var source = @" class B { public static void F1() where T11 : INode where T12 : class?, T11, INode {} public static void F2() where T21 : INode? where T22 : class?, T21, INode {} public static void F3() where T31 : INode? where T32 : class?, T31, INode? {} public static void F4() where T41 : INode? where T42 : class?, T41?, INode? {} } interface INode {} interface INode {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,89): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3() where T31 : INode? where T32 : class?, T31, INode? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T32?").WithLocation(10, 89), // (13,78): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F4() where T41 : INode? where T42 : class?, T41?, INode? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T41?").WithLocation(13, 78), // (13,90): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F4() where T41 : INode? where T42 : class?, T41?, INode? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T42?").WithLocation(13, 90) ); } [Fact] public void Constraints_16() { var source = @" class B { public static void F1(T12? t1) where T11 : INode where T12 : class?, T11 {} public static void F2(T22? t2) where T21 : INode? where T22 : class?, T21 {} public static void F3(T32? t1) where T31 : INode where T32 : class?, T31? {} } interface INode {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,37): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F2(T22? t2) where T21 : INode? where T22 : class?, T21 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T22?").WithLocation(7, 37), // (10,37): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3(T32? t1) where T31 : INode where T32 : class?, T31? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T32?").WithLocation(10, 37), // (10,84): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F3(T32? t1) where T31 : INode where T32 : class?, T31? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T31?").WithLocation(10, 84) ); } [Fact] public void Constraints_17() { var source = @" #pragma warning disable CS8321 class B<[System.Runtime.CompilerServices.Nullable(0)] T1> { public static void F2<[System.Runtime.CompilerServices.Nullable(1)] T2>(T2 t2) { void F3<[System.Runtime.CompilerServices.Nullable(2)] T3>(T3 t3) { } } }"; var comp = CreateCompilation(new[] { source, NullableAttributeDefinition }); comp.VerifyDiagnostics( // (4,10): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // class B<[System.Runtime.CompilerServices.Nullable(0)] T1> Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "System.Runtime.CompilerServices.Nullable(0)").WithLocation(4, 10), // (6,28): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // public static void F2<[System.Runtime.CompilerServices.Nullable(1)] T2>(T2 t2) Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "System.Runtime.CompilerServices.Nullable(1)").WithLocation(6, 28), // (8,17): error CS8205: Attributes are not allowed on local function parameters or type parameters // void F3<[System.Runtime.CompilerServices.Nullable(2)] T3>(T3 t3) Diagnostic(ErrorCode.ERR_AttributesInLocalFuncDecl, "[System.Runtime.CompilerServices.Nullable(2)]").WithLocation(8, 17), // (8,18): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // void F3<[System.Runtime.CompilerServices.Nullable(2)] T3>(T3 t3) Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "System.Runtime.CompilerServices.Nullable(2)").WithLocation(8, 18) ); } [Fact] public void Constraints_18() { var source = @" class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } class B : A { public override void F1(T11? t1) { } public override void F2(T22 t2) { } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,26): error CS0115: 'B.F1(T11?)': no suitable method found to override // public override void F1(T11? t1) where T : class Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F1").WithArguments("B.F1(T11?)").WithLocation(15, 26), // (15,39): error CS0453: The type 'T11' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void F1(T11? t1) where T : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "t1").WithArguments("System.Nullable", "T", "T11").WithLocation(15, 39)); } [Fact] public void Constraints_19() { var source1 = @" public class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var source2 = @" class B : A { public override void F1(T11? t1) { } public override void F2(T22 t2) { } } "; var comp2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }) .VerifyDiagnostics( // (4,26): error CS0115: 'B.F1(T11?)': no suitable method found to override // public override void F1(T11? t1) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F1").WithArguments("B.F1(T11?)").WithLocation(4, 26), // (4,39): error CS0453: The type 'T11' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void F1(T11? t1) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "t1").WithArguments("System.Nullable", "T", "T11").WithLocation(4, 39)); } [Fact] public void Constraints_20() { var source1 = @" public class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var source3 = @" class B : A { public override void F1(T11? t1) { } public override void F2(T22 t2) { } } "; var comp3 = CreateCompilation(new[] { source3 }, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }, parseOptions: TestOptions.Regular8).VerifyDiagnostics( // (4,26): error CS0115: 'B.F1(T11?)': no suitable method found to override // public override void F1(T11? t1) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F1").WithArguments("B.F1(T11?)").WithLocation(4, 26), // (4,39): error CS0453: The type 'T11' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void F1(T11? t1) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "t1").WithArguments("System.Nullable", "T", "T11").WithLocation(4, 39)); } [Fact] public void Constraints_21() { var source1 = @" public class A { public virtual void F1() where T1 : class { } public virtual void F2() where T2 : class? { } } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var source2 = @" class B : A { public override void F1() { } public override void F2() { } } "; var comp2 = CreateCompilation(new[] { source2 }, references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", bf2.GetAttributes().Single().ToString()); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); } } [Fact] public void Constraints_22() { var source = @" class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } class B : A { public override void F1(T11? t1) { } public override void F2(T22 t2) { } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,26): error CS0115: 'B.F1(T11?)': no suitable method found to override // public override void F1(T11? t1) Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F1").WithArguments("B.F1(T11?)").WithLocation(15, 26), // (15,39): error CS0453: The type 'T11' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // public override void F1(T11? t1) Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "t1").WithArguments("System.Nullable", "T", "T11").WithLocation(15, 39)); var bf1 = (MethodSymbol)comp.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T11? t1)", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.IsReferenceType); Assert.Null(bf1.OverriddenMethod); var bf2 = (MethodSymbol)comp.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T22 t2) where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); var af2 = bf2.OverriddenMethod; Assert.Equal("void A.F2(T2 t2) where T2 : class?", af2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = af2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); } [Fact] public void Constraints_23() { var source1 = @" public interface IA { void F1() where T1 : class?; void F2() where T2 : class; void F3() where T3 : C1; void F4() where T4 : C1; void F5() where T51 : class where T52 : C1; void F6() where T61 : class where T62 : C1; } public class C1 {} public class C2 {} "; var source2 = @" class B : IA { public void F1() where T11 : class { } public void F2() where T22 : class? { } public void F3() where T33 : C1 { } public void F4() where T44 : C1? { } public void F5() where T551 : class where T552 : C1 { } public void F6() where T661 : class where T662 : C1 { } } class D : IA { public void F1() where T111 : class? { } public void F2() where T222 : class { } public void F3() where T333 : C1 { } public void F4() where T444 : C1 { } public void F5() where T5551 : class where T5552 : C1 { } public void F6() where T6661 : class where T6662 : C1 { } } "; var comp1 = CreateCompilation(new[] { source2, source1 }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T11' of method 'B.F1()' doesn't match the constraints for type parameter 'T1' of interface method 'IA.F1()'. Consider using an explicit interface implementation instead. // public void F1() where T11 : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("T11", "B.F1()", "T1", "IA.F1()").WithLocation(4, 17), // (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(8, 17), // (12,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(12, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'T44' of method 'B.F4()' doesn't match the constraints for type parameter 'T4' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T44 : C1? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T44", "B.F4()", "T4", "IA.F4()").WithLocation(16, 17), // (20,17): warning CS8633: Nullability in constraints for type parameter 'T552' of method 'B.F5()' doesn't match the constraints for type parameter 'T52' of interface method 'IA.F5()'. Consider using an explicit interface implementation instead. // public void F5() where T551 : class where T552 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F5").WithArguments("T552", "B.F5()", "T52", "IA.F5()").WithLocation(20, 17), // (24,17): warning CS8633: Nullability in constraints for type parameter 'T662' of method 'B.F6()' doesn't match the constraints for type parameter 'T62' of interface method 'IA.F6()'. Consider using an explicit interface implementation instead. // public void F6() where T661 : class where T662 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F6").WithArguments("T662", "B.F6()", "T62", "IA.F6()").WithLocation(24, 17) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", bf2.GetAttributes().Single().ToString()); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); var bf3 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F3"); Assert.Equal("void B.F3() where T33 : C1!", bf3.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); var bf4 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F4"); Assert.Equal("void B.F4() where T44 : C1?", bf4.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } var comp2 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); comp2.VerifyDiagnostics( ); var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }); comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(8, 17), // (12,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(12, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'T44' of method 'B.F4()' doesn't match the constraints for type parameter 'T4' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T44 : C1? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T44", "B.F4()", "T4", "IA.F4()").WithLocation(16, 17), // (20,17): warning CS8633: Nullability in constraints for type parameter 'T552' of method 'B.F5()' doesn't match the constraints for type parameter 'T52' of interface method 'IA.F5()'. Consider using an explicit interface implementation instead. // public void F5() where T551 : class where T552 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F5").WithArguments("T552", "B.F5()", "T52", "IA.F5()").WithLocation(20, 17), // (20,69): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F5() where T551 : class where T552 : C1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T551?").WithLocation(20, 69), // (51,73): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F6() where T6661 : class where T6662 : C1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T6661?").WithLocation(51, 73) ); var comp4 = CreateCompilation(new[] { source1 }); var comp5 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp4.ToMetadataReference() }); comp5.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T11' of method 'B.F1()' doesn't match the constraints for type parameter 'T1' of interface method 'IA.F1()'. Consider using an explicit interface implementation instead. // public void F1() where T11 : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("T11", "B.F1()", "T1", "IA.F1()").WithLocation(4, 17), // (24,17): warning CS8633: Nullability in constraints for type parameter 'T662' of method 'B.F6()' doesn't match the constraints for type parameter 'T62' of interface method 'IA.F6()'. Consider using an explicit interface implementation instead. // public void F6() where T661 : class where T662 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F6").WithArguments("T662", "B.F6()", "T62", "IA.F6()").WithLocation(24, 17) ); } [Fact] public void Constraints_24() { var source = @" interface IA { void F1() where T1 : class; void F2() where T2 : class?; } class B : IA { void IA.F1() { } void IA.F2() { } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All))); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F1"); Assert.Equal("void B.IA.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F2"); Assert.Equal("void B.IA.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", bf2.GetAttributes().Single().ToString()); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); } } [Fact] public void Constraints_25() { var source1 = @" public interface IA { void F1() where T1 : class; void F2() where T2 : class?; } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var source2 = @" class B : IA { void IA.F1() { } void IA.F2() { } } "; var comp2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)), references: new[] { comp1.EmitToImageReference() }); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F1"); Assert.Equal("void B.IA.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F2"); Assert.Equal("void B.IA.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { CSharpAttributeData nullableAttribute = bf2.GetAttributes().Single(); Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", nullableAttribute.ToString()); Assert.Same(m, nullableAttribute.AttributeClass.ContainingModule); Assert.Equal(Accessibility.Internal, nullableAttribute.AttributeClass.DeclaredAccessibility); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); } } [Fact] public void Constraints_26() { var source1 = @" public interface IA { void F1() where T1 : class; void F2() where T2 : class?; } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var comp2 = CreateCompilation(NullableContextAttributeDefinition); var source3 = @" class B : IA { void IA.F1() { } void IA.F2() { } } "; var comp3 = CreateCompilation(new[] { source3 }, options: WithNonNullTypesTrue(TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)), references: new[] { comp1.EmitToImageReference(), comp2.EmitToImageReference() }); comp3.VerifyDiagnostics( ); CompileAndVerify(comp3, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F1"); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } Assert.Equal("void B.IA.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F2"); Assert.Equal("void B.IA.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { CSharpAttributeData nullableAttribute = bf2.GetAttributes().Single(); Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", nullableAttribute.ToString()); Assert.NotEqual(m, nullableAttribute.AttributeClass.ContainingModule); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); } } [Fact] public void Constraints_27() { var source1 = @" public interface IA { void F1() where T1 : class; void F2() where T2 : class?; } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var source2 = @" class B : IA { void IA.F1() { } void IA.F2() { } } "; var comp2 = CreateCompilation(new[] { source2 }, references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F1"); Assert.Equal("void B.IA.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.IA.F2"); Assert.Equal("void B.IA.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", bf2.GetAttributes().Single().ToString()); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); } } [Fact] public void Constraints_28() { var source = @" interface IA { void F1(T1? t1) where T1 : class; void F2(T2 t2) where T2 : class?; } class B : IA { void IA.F1(T11? t1) where T11 : class? { } void IA.F2(T22 t2) where T22 : class { } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,42): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint. // void IA.F1(T11? t1) where T11 : class? Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "class?").WithLocation(10, 42)); var bf1 = (MethodSymbol)comp.GlobalNamespace.GetMember("B.IA.F1"); Assert.Equal("void B.IA.F1(T11? t1) where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.True(t11.IsReferenceType); var bf2 = (MethodSymbol)comp.GlobalNamespace.GetMember("B.IA.F2"); Assert.Equal("void B.IA.F2(T22 t2) where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); } [Fact] public void Constraints_29() { var source = @" class B { public static void F2() where T2 : class? { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2() where T2 : class?", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(f2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", f2.GetAttributes().Single().ToString()); } TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); Assert.Empty(t2.GetAttributes()); } } [Fact] public void Constraints_30() { var source = @" class B where T2 : class? { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var b = (NamedTypeSymbol)m.GlobalNamespace.GetMember("B"); Assert.Equal("B where T2 : class?", b.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = b.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t2.GetAttributes().Single().ToString()); } } } [Fact] public void Constraints_31() { var source = @" #pragma warning disable CS8321 class B { public static void Test() { void F2() where T2 : class? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var localSyntaxes = tree.GetRoot().DescendantNodes().OfType().ToArray(); Assert.Equal(1, localSyntaxes.Length); var f2 = (LocalFunctionSymbol)model.GetDeclaredSymbol(localSyntaxes[0]); Assert.Equal("void F2() where T2 : class?", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); Assert.Empty(t2.GetAttributes()); } [Fact] public void Constraints_32() { var source = @" #pragma warning disable CS8321 class B where T1 : struct? { public static void F2(T2 t2) where T2 : struct? { void F3(T3 t3) where T3 : struct? { } } }"; var comp = CreateCompilation(source); var expected = new[] { // (4,30): error CS1073: Unexpected token '?' // class B where T1 : struct? Diagnostic(ErrorCode.ERR_UnexpectedToken, "?").WithArguments("?").WithLocation(4, 30), // (6,55): error CS1073: Unexpected token '?' // public static void F2(T2 t2) where T2 : struct? Diagnostic(ErrorCode.ERR_UnexpectedToken, "?").WithArguments("?").WithLocation(6, 55), // (8,45): error CS1073: Unexpected token '?' // void F3(T3 t3) where T3 : struct? Diagnostic(ErrorCode.ERR_UnexpectedToken, "?").WithArguments("?").WithLocation(8, 45) }; comp.VerifyDiagnostics(expected); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(expected); comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(expected); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); comp.VerifyDiagnostics(expected .Concat(new[] { // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.3", "preview").WithLocation(1, 1) }).ToArray() ); } [Fact] public void Constraints_33() { var source = @" interface IA { } class C where TC : IA, IA { } class B where TB : IA, IA { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,36): error CS0405: Duplicate constraint 'IA' for type parameter 'TC' // class C where TC : IA, IA Diagnostic(ErrorCode.ERR_DuplicateBound, "IA").WithArguments("IA", "TC").WithLocation(5, 36), // (8,37): error CS0405: Duplicate constraint 'IA' for type parameter 'TB' // class B where TB : IA, IA Diagnostic(ErrorCode.ERR_DuplicateBound, "IA").WithArguments("IA", "TB").WithLocation(8, 37) ); } [Fact] public void Constraints_34() { var source = @" interface IA { } class B where TB : IA?, IA { } class C where TC : IA, IA? { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,37): error CS0405: Duplicate constraint 'IA' for type parameter 'TB' // class B where TB : IA?, IA Diagnostic(ErrorCode.ERR_DuplicateBound, "IA").WithArguments("IA", "TB").WithLocation(5, 37), // (8,36): error CS0405: Duplicate constraint 'IA' for type parameter 'TC' // class C where TC : IA, IA? Diagnostic(ErrorCode.ERR_DuplicateBound, "IA?").WithArguments("IA", "TC").WithLocation(8, 36) ); } [Fact] public void Constraints_35() { var source1 = @" public interface IA { void F1() where T1 : class?; void F2() where T2 : class; void F3() where T3 : C1; void F4() where T4 : C1; void F5() where T51 : class where T52 : C1; void F6() where T61 : class where T62 : C1; } public class C1 {} public class C2 {} "; var source2 = @" class B : IA { public void F1() where T11 : class { } public void F2() where T22 : class? { } public void F3() where T33 : C1 { } public void F4() where T44 : C1? { } public void F5() where T551 : class where T552 : C1 { } public void F6() where T661 : class where T662 : C1 { } } class D : IA { public void F1() where T111 : class? { } public void F2() where T222 : class { } public void F3() where T333 : C1 { } public void F4() where T444 : C1 { } public void F5() where T5551 : class where T5552 : C1 { } public void F6() where T6661 : class where T6662 : C1 { } } "; var comp1 = CreateCompilation(new[] { source2, source1 }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T11' of method 'B.F1()' doesn't match the constraints for type parameter 'T1' of interface method 'IA.F1()'. Consider using an explicit interface implementation instead. // public void F1() where T11 : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("T11", "B.F1()", "T1", "IA.F1()").WithLocation(4, 17), // (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(8, 17), // (12,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(12, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'T44' of method 'B.F4()' doesn't match the constraints for type parameter 'T4' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T44 : C1? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T44", "B.F4()", "T4", "IA.F4()").WithLocation(16, 17), // (20,17): warning CS8633: Nullability in constraints for type parameter 'T552' of method 'B.F5()' doesn't match the constraints for type parameter 'T52' of interface method 'IA.F5()'. Consider using an explicit interface implementation instead. // public void F5() where T551 : class where T552 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F5").WithArguments("T552", "B.F5()", "T52", "IA.F5()").WithLocation(20, 17), // (24,17): warning CS8633: Nullability in constraints for type parameter 'T662' of method 'B.F6()' doesn't match the constraints for type parameter 'T62' of interface method 'IA.F6()'. Consider using an explicit interface implementation instead. // public void F6() where T661 : class where T662 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F6").WithArguments("T662", "B.F6()", "T62", "IA.F6()").WithLocation(24, 17) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2() where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(bf2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", bf2.GetAttributes().Single().ToString()); } TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); Assert.Empty(t22.GetAttributes()); var bf3 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F3"); Assert.Equal("void B.F3() where T33 : C1!", bf3.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); var bf4 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F4"); Assert.Equal("void B.F4() where T44 : C1?", bf4.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } var comp2 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); comp2.VerifyDiagnostics( ); var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }); comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(8, 17), // (12,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(12, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'T44' of method 'B.F4()' doesn't match the constraints for type parameter 'T4' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T44 : C1? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T44", "B.F4()", "T4", "IA.F4()").WithLocation(16, 17), // (20,17): warning CS8633: Nullability in constraints for type parameter 'T552' of method 'B.F5()' doesn't match the constraints for type parameter 'T52' of interface method 'IA.F5()'. Consider using an explicit interface implementation instead. // public void F5() where T551 : class where T552 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F5").WithArguments("T552", "B.F5()", "T52", "IA.F5()").WithLocation(20, 17), // (20,69): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F5() where T551 : class where T552 : C1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T551?").WithLocation(20, 69), // (51,73): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F6() where T6661 : class where T6662 : C1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T6661?").WithLocation(51, 73) ); var comp4 = CreateCompilation(new[] { source1 }); var comp5 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp4.ToMetadataReference() }); comp5.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T11' of method 'B.F1()' doesn't match the constraints for type parameter 'T1' of interface method 'IA.F1()'. Consider using an explicit interface implementation instead. // public void F1() where T11 : class Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("T11", "B.F1()", "T1", "IA.F1()").WithLocation(4, 17), // (24,17): warning CS8633: Nullability in constraints for type parameter 'T662' of method 'B.F6()' doesn't match the constraints for type parameter 'T62' of interface method 'IA.F6()'. Consider using an explicit interface implementation instead. // public void F6() where T661 : class where T662 : C1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F6").WithArguments("T662", "B.F6()", "T62", "IA.F6()").WithLocation(24, 17) ); } [Fact] public void Constraints_36() { var source1 = @" public interface IA { void F1() where T1 : class?, IB, IC?; void F2() where T2 : class, IB?, IC?; void F3() where T3 : class?, IB?, IC; void F4() where T41 : class where T42 : T41?, IB, IC?; void F5() where T51 : class where T52 : T51, IB?, IC?; void F6() where T61 : class where T62 : T61?, IB?, IC; void F7() where T71 : class? where T72 : T71, IB, IC?; void F8() where T81 : class where T82 : T81, IB?, IC?; void F9() where T91 : class? where T92 : T91, IB?, IC; } public interface IB {} public interface IC {} "; var source2 = @" class B : IA { public void F1() where T11 : class, IB, IC { } public void F2() where T22 : class, IB, IC { } public void F3() where T33 : class, IB, IC { } public void F4() where T441 : class where T442 : T441, IB, IC { } public void F5() where T551 : class where T552 : T551, IB, IC { } public void F6() where T661 : class where T662 : T661, IB, IC { } public void F7() where T771 : class where T772 : T771, IB, IC { } public void F8() where T881 : class where T882 : T881, IB, IC { } public void F9() where T991 : class where T992 : T991, IB, IC { } } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var comp2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); var expected = new[] { // (36,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : class where T992 : T991, IB, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(36, 17), // (28,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : class where T772 : T771, IB, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(28, 17) }; comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp3.VerifyDiagnostics(expected); var comp4 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesFalse(), references: new[] { comp1.ToMetadataReference() }); comp4.VerifyDiagnostics(); var comp5 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesFalse(), references: new[] { comp1.EmitToImageReference() }); comp5.VerifyDiagnostics(); var comp6 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesFalse()); comp6.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (7,55): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F4() where T41 : class where T42 : T41?, IB, IC?; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T41?").WithLocation(7, 55), // (9,55): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F6() where T61 : class where T62 : T61?, IB?, IC; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T61?").WithLocation(9, 55) ); var comp7 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp6.ToMetadataReference() }); comp7.VerifyDiagnostics(expected); var comp9 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesFalse(), references: new[] { comp6.ToMetadataReference() }); comp9.VerifyDiagnostics(); } [Fact] public void Constraints_37() { var source = @" public interface IA { void F1() where T1 : class, IB, IC; void F2() where T2 : class, IB, IC; void F3() where T3 : class, IB, IC; void F4() where T41 : class where T42 : T41, IB, IC; void F5() where T51 : class where T52 : T51, IB, IC; void F6() where T61 : class where T62 : T61, IB, IC; void F7() where T71 : class where T72 : T71, IB, IC; void F8() where T81 : class where T82 : T81, IB, IC; void F9() where T91 : class where T92 : T91, IB, IC; } public interface IB {} public interface IC {} class B : IA { public void F1() where T11 : class?, IB, IC? { } public void F2() where T22 : class, IB?, IC? { } public void F3() where T33 : class?, IB?, IC { } public void F4() where T441 : class where T442 : T441?, IB, IC? { } public void F5() where T551 : class where T552 : T551, IB?, IC? { } public void F6() where T661 : class where T662 : T661?, IB?, IC { } public void F7() where T771 : class? where T772 : T771, IB, IC? { } public void F8() where T881 : class where T882 : T881, IB?, IC? { } public void F9() where T991 : class? where T992 : T991, IB?, IC { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (55,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : class? where T992 : T991, IB?, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(55, 17), // (47,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : class? where T772 : T771, IB, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(47, 17) ); } [Fact] public void Constraints_38() { var source = @" public interface IA { void F1() where T1 : ID?, IB, IC?; void F2() where T2 : ID, IB?, IC?; void F3() where T3 : ID?, IB?, IC; void F4() where T41 : ID where T42 : T41?, IB, IC?; void F5() where T51 : ID where T52 : T51, IB?, IC?; void F6() where T61 : ID where T62 : T61?, IB?, IC; void F7() where T71 : ID? where T72 : T71, IB, IC?; void F8() where T81 : ID where T82 : T81, IB?, IC?; void F9() where T91 : ID? where T92 : T91, IB?, IC; } public interface IB {} public interface IC {} public interface ID {} class B : IA { public void F1() where T11 : ID, IB, IC { } public void F2() where T22 : ID, IB, IC { } public void F3() where T33 : ID, IB, IC { } public void F4() where T441 : ID where T442 : T441, IB, IC { } public void F5() where T551 : ID where T552 : T551, IB, IC { } public void F6() where T661 : ID where T662 : T661, IB, IC { } public void F7() where T771 : ID where T772 : T771, IB, IC { } public void F8() where T881 : ID where T882 : T881, IB, IC { } public void F9() where T991 : ID where T992 : T991, IB, IC { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (7,52): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F4() where T41 : ID where T42 : T41?, IB, IC?; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T41?").WithLocation(7, 52), // (9,52): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F6() where T61 : ID where T62 : T61?, IB?, IC; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T61?").WithLocation(9, 52), // (58,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : ID where T992 : T991, IB, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(58, 17), // (50,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : ID where T772 : T771, IB, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(50, 17) ); } [Fact] public void Constraints_39() { var source = @" public interface IA { void F1() where T1 : ID, IB, IC; void F2() where T2 : ID, IB, IC; void F3() where T3 : ID, IB, IC; void F4() where T41 : ID where T42 : T41, IB, IC; void F5() where T51 : ID where T52 : T51, IB, IC; void F6() where T61 : ID where T62 : T61, IB, IC; void F7() where T71 : ID where T72 : T71, IB, IC; void F8() where T81 : ID where T82 : T81, IB, IC; void F9() where T91 : ID where T92 : T91, IB, IC; } public interface IB {} public interface IC {} public interface ID {} class B : IA { public void F1() where T11 : ID?, IB, IC? { } public void F2() where T22 : ID, IB?, IC? { } public void F3() where T33 : ID?, IB?, IC { } public void F4() where T441 : ID where T442 : T441?, IB, IC? { } public void F5() where T551 : ID where T552 : T551, IB?, IC? { } public void F6() where T661 : ID where T662 : T661?, IB?, IC { } public void F7() where T771 : ID? where T772 : T771, IB, IC? { } public void F8() where T881 : ID where T882 : T881, IB?, IC? { } public void F9() where T991 : ID? where T992 : T991, IB?, IC { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (38,63): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F4() where T441 : ID where T442 : T441?, IB, IC? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T441?").WithLocation(38, 63), // (46,63): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F6() where T661 : ID where T662 : T661?, IB?, IC Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T661?").WithLocation(46, 63), // (58,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : ID? where T992 : T991, IB?, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(58, 17), // (50,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : ID? where T772 : T771, IB, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(50, 17) ); } [Fact] public void Constraints_40() { var source = @" public interface IA { void F1() where T1 : D?, IB, IC?; void F2() where T2 : D, IB?, IC?; void F3() where T3 : D?, IB?, IC; void F4() where T41 : D where T42 : T41?, IB, IC?; void F5() where T51 : D where T52 : T51, IB?, IC?; void F6() where T61 : D where T62 : T61?, IB?, IC; void F7() where T71 : D? where T72 : T71, IB, IC?; void F8() where T81 : D where T82 : T81, IB?, IC?; void F9() where T91 : D? where T92 : T91, IB?, IC; } public interface IB {} public interface IC {} public class D {} class B : IA { public void F1() where T11 : D, IB, IC { } public void F2() where T22 : D, IB, IC { } public void F3() where T33 : D, IB, IC { } public void F4() where T441 : D where T442 : T441, IB, IC { } public void F5() where T551 : D where T552 : T551, IB, IC { } public void F6() where T661 : D where T662 : T661, IB, IC { } public void F7() where T771 : D where T772 : T771, IB, IC { } public void F8() where T881 : D where T882 : T881, IB, IC { } public void F9() where T991 : D where T992 : T991, IB, IC { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (58,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : D where T992 : T991, IB, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(58, 17), // (50,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : D where T772 : T771, IB, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(50, 17) ); } [Fact] public void Constraints_41() { var source = @" public interface IA { void F1() where T1 : D, IB, IC; void F2() where T2 : D, IB, IC; void F3() where T3 : D, IB, IC; void F4() where T41 : D where T42 : T41, IB, IC; void F5() where T51 : D where T52 : T51, IB, IC; void F6() where T61 : D where T62 : T61, IB, IC; void F7() where T71 : D where T72 : T71, IB, IC; void F8() where T81 : D where T82 : T81, IB, IC; void F9() where T91 : D where T92 : T91, IB, IC; } public interface IB {} public interface IC {} public class D {} class B : IA { public void F1() where T11 : D?, IB, IC? { } public void F2() where T22 : D, IB?, IC? { } public void F3() where T33 : D?, IB?, IC { } public void F4() where T441 : D where T442 : T441?, IB, IC? { } public void F5() where T551 : D where T552 : T551, IB?, IC? { } public void F6() where T661 : D where T662 : T661?, IB?, IC { } public void F7() where T771 : D? where T772 : T771, IB, IC? { } public void F8() where T881 : D where T882 : T881, IB?, IC? { } public void F9() where T991 : D? where T992 : T991, IB?, IC { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (58,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : D? where T992 : T991, IB?, IC Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(58, 17), // (50,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : D? where T772 : T771, IB, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(50, 17) ); } [Fact] public void Constraints_42() { var source = @" public interface IA { void F1() where T1 : class?, IB?, IC?; void F2() where T2 : class?, IB?, IC?; void F3() where T3 : class?, IB?, IC?; void F4() where T41 : class? where T42 : T41, IB?, IC?; void F5() where T51 : class? where T52 : T51, IB?, IC?; void F6() where T61 : class? where T62 : T61, IB?, IC?; void F7() where T71 : class where T72 : T71?, IB?, IC?; void F8() where T81 : class where T82 : T81?, IB?, IC?; void F9() where T91 : class where T92 : T91?, IB?, IC?; } public interface IB {} public interface IC {} class B : IA { public void F1() where T11 : class?, IB?, IC? { } public void F2() where T22 : class?, IB?, IC? { } public void F3() where T33 : class?, IB?, IC? { } public void F4() where T441 : class where T442 : T441?, IB?, IC? { } public void F5() where T551 : class where T552 : T551?, IB?, IC? { } public void F6() where T661 : class where T662 : T661?, IB?, IC? { } public void F7() where T771 : class? where T772 : T771, IB?, IC? { } public void F8() where T881 : class? where T882 : T881, IB?, IC? { } public void F9() where T991 : class? where T992 : T991, IB?, IC? { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (55,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : class? where T992 : T991, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(55, 17), // (35,17): warning CS8633: Nullability in constraints for type parameter 'T441' of method 'B.F4()' doesn't match the constraints for type parameter 'T41' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T441 : class where T442 : T441?, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T441", "B.F4()", "T41", "IA.F4()").WithLocation(35, 17), // (39,17): warning CS8633: Nullability in constraints for type parameter 'T551' of method 'B.F5()' doesn't match the constraints for type parameter 'T51' of interface method 'IA.F5()'. Consider using an explicit interface implementation instead. // public void F5() where T551 : class where T552 : T551?, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F5").WithArguments("T551", "B.F5()", "T51", "IA.F5()").WithLocation(39, 17), // (43,17): warning CS8633: Nullability in constraints for type parameter 'T661' of method 'B.F6()' doesn't match the constraints for type parameter 'T61' of interface method 'IA.F6()'. Consider using an explicit interface implementation instead. // public void F6() where T661 : class where T662 : T661?, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F6").WithArguments("T661", "B.F6()", "T61", "IA.F6()").WithLocation(43, 17), // (47,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : class? where T772 : T771, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(47, 17), // (51,17): warning CS8633: Nullability in constraints for type parameter 'T881' of method 'B.F8()' doesn't match the constraints for type parameter 'T81' of interface method 'IA.F8()'. Consider using an explicit interface implementation instead. // public void F8() where T881 : class? where T882 : T881, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F8").WithArguments("T881", "B.F8()", "T81", "IA.F8()").WithLocation(51, 17) ); } [Fact] public void Constraints_43() { var source = @" public interface IA { void F7() where T71 : class where T72 : T71?, IB?, IC?; void F8() where T81 : class where T82 : T81?, IB?, IC?; void F9() where T91 : class where T92 : T91?, IB?, IC?; } public interface IB {} public interface IC {} class B : IA { public void F7() where T771 : class? where T772 : T771?, IB?, IC? { } public void F8() where T881 : class? where T882 : T881?, IB?, IC? { } public void F9() where T991 : class? where T992 : T991?, IB?, IC? { } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (25,67): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F9() where T991 : class? where T992 : T991?, IB?, IC? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T991?").WithLocation(25, 67), // (21,67): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F8() where T881 : class? where T882 : T881?, IB?, IC? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T881?").WithLocation(21, 67), // (17,67): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public void F7() where T771 : class? where T772 : T771?, IB?, IC? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T771?").WithLocation(17, 67), // (25,17): warning CS8633: Nullability in constraints for type parameter 'T991' of method 'B.F9()' doesn't match the constraints for type parameter 'T91' of interface method 'IA.F9()'. Consider using an explicit interface implementation instead. // public void F9() where T991 : class? where T992 : T991?, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F9").WithArguments("T991", "B.F9()", "T91", "IA.F9()").WithLocation(25, 17), // (21,17): warning CS8633: Nullability in constraints for type parameter 'T881' of method 'B.F8()' doesn't match the constraints for type parameter 'T81' of interface method 'IA.F8()'. Consider using an explicit interface implementation instead. // public void F8() where T881 : class? where T882 : T881?, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F8").WithArguments("T881", "B.F8()", "T81", "IA.F8()").WithLocation(21, 17), // (17,17): warning CS8633: Nullability in constraints for type parameter 'T771' of method 'B.F7()' doesn't match the constraints for type parameter 'T71' of interface method 'IA.F7()'. Consider using an explicit interface implementation instead. // public void F7() where T771 : class? where T772 : T771?, IB?, IC? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F7").WithArguments("T771", "B.F7()", "T71", "IA.F7()").WithLocation(17, 17) ); } [Fact] public void Constraints_44() { var source1 = @" public interface IA { void F1() where T1 : class?, IB?; void F2() where T2 : class, IB?; void F3() where T3 : C1, IB?; void F4() where T4 : C1?, IB?; } public class C1 {} public interface IB {} "; var source2 = @" class B : IA { public void F1() where T11 : class, IB? { } public void F2() where T22 : class?, IB? { } public void F3() where T33 : C1?, IB? { } public void F4() where T44 : C1, IB? { } } class D : IA { public void F1() where T111 : class?, IB? { } public void F2() where T222 : class, IB? { } public void F3() where T333 : C1, IB? { } public void F4() where T444 : C1?, IB? { } } "; var comp1 = CreateCompilation(new[] { source2, source1 }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T11' of method 'B.F1()' doesn't match the constraints for type parameter 'T1' of interface method 'IA.F1()'. Consider using an explicit interface implementation instead. // public void F1() where T11 : class, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("T11", "B.F1()", "T1", "IA.F1()").WithLocation(4, 17), // (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(8, 17), // (12,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(12, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'T44' of method 'B.F4()' doesn't match the constraints for type parameter 'T4' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T44 : C1, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T44", "B.F4()", "T4", "IA.F4()").WithLocation(16, 17) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.True(t11.IsNotNullable); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.False(t22.IsNotNullable); var bf3 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F3"); TypeParameterSymbol t33 = bf3.TypeParameters[0]; Assert.False(t33.IsNotNullable); var bf4 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F4"); TypeParameterSymbol t44 = bf4.TypeParameters[0]; Assert.True(t44.IsNotNullable); } var comp2 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); comp2.VerifyDiagnostics( ); var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }); comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(8, 17), // (12,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(12, 17) ); symbolValidator2(comp3.SourceModule); void symbolValidator2(ModuleSymbol m) { var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.Null(t11.IsNotNullable); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.False(t22.IsNotNullable); var bf3 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F3"); TypeParameterSymbol t33 = bf3.TypeParameters[0]; Assert.False(t33.IsNotNullable); var bf4 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F4"); TypeParameterSymbol t44 = bf4.TypeParameters[0]; Assert.Null(t44.IsNotNullable); } var comp4 = CreateCompilation(new[] { source1 }); var comp5 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp4.ToMetadataReference() }); comp5.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T11' of method 'B.F1()' doesn't match the constraints for type parameter 'T1' of interface method 'IA.F1()'. Consider using an explicit interface implementation instead. // public void F1() where T11 : class, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("T11", "B.F1()", "T1", "IA.F1()").WithLocation(4, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'T44' of method 'B.F4()' doesn't match the constraints for type parameter 'T4' of interface method 'IA.F4()'. Consider using an explicit interface implementation instead. // public void F4() where T44 : C1, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F4").WithArguments("T44", "B.F4()", "T4", "IA.F4()").WithLocation(16, 17) ); symbolValidator1(comp5.SourceModule); var comp6 = CreateCompilation(new[] { source2 }, references: new[] { comp4.ToMetadataReference() }); comp6.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( ); symbolValidator2(comp6.SourceModule); } [Fact] public void Constraints_45() { var source1 = @" public interface IA { void F2() where T2 : class?, IB; void F3() where T3 : C1?, IB; } public class C1 {} public interface IB {} "; var source2 = @" class B : IA { public void F2() where T22 : class?, IB? { } public void F3() where T33 : C1?, IB? { } } class D : IA { public void F2() where T222 : class?, IB { } public void F3() where T333 : C1?, IB { } } "; var comp1 = CreateCompilation(new[] { source2, source1 }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(4, 17), // (8,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(8, 17) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("D.F2"); TypeParameterSymbol t222 = bf2.TypeParameters[0]; Assert.True(t222.IsNotNullable); var bf3 = (MethodSymbol)m.GlobalNamespace.GetMember("D.F3"); TypeParameterSymbol t333 = bf3.TypeParameters[0]; Assert.True(t333.IsNotNullable); } var comp2 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); comp2.VerifyDiagnostics( ); var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }); comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (4,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2()'. Consider using an explicit interface implementation instead. // public void F2() where T22 : class?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("T22", "B.F2()", "T2", "IA.F2()").WithLocation(4, 17), // (8,17): warning CS8633: Nullability in constraints for type parameter 'T33' of method 'B.F3()' doesn't match the constraints for type parameter 'T3' of interface method 'IA.F3()'. Consider using an explicit interface implementation instead. // public void F3() where T33 : C1?, IB? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F3").WithArguments("T33", "B.F3()", "T3", "IA.F3()").WithLocation(8, 17) ); symbolValidator2(comp3.SourceModule); void symbolValidator2(ModuleSymbol m) { var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("D.F2"); TypeParameterSymbol t222 = bf2.TypeParameters[0]; Assert.Null(t222.IsNotNullable); var bf3 = (MethodSymbol)m.GlobalNamespace.GetMember("D.F3"); TypeParameterSymbol t333 = bf3.TypeParameters[0]; Assert.Null(t333.IsNotNullable); } var comp4 = CreateCompilation(new[] { source1 }); var comp5 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp4.ToMetadataReference() }); comp5.VerifyDiagnostics( ); symbolValidator1(comp5.SourceModule); var comp6 = CreateCompilation(new[] { source2 }, references: new[] { comp4.ToMetadataReference() }); comp6.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( ); symbolValidator2(comp6.SourceModule); } [Fact] public void Constraints_46() { var source = @" class B { public static void F1() where T1 : notnull { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T1 : notnull", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(f1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", f1.GetAttributes().Single().ToString()); } TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.IsReferenceType); Assert.True(t1.IsNotNullable); var attributes = t1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_47() { var source = @" class B { public static void F1() where T1 : notnull { } }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T1 : notnull", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(f1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", f1.GetAttributes().Single().ToString()); } TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.IsReferenceType); Assert.True(t1.HasNotNullConstraint); Assert.True(t1.IsNotNullable); var attributes = t1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_48() { var source = @" class B { public static void F1(T1? t1) where T1 : object? { } public static void F2(T2? t2) where T2 : System.Object? { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,31): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F1(T1? t1) where T1 : object? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T1?").WithLocation(4, 31), // (4,50): error CS0702: Constraint cannot be special class 'object' // public static void F1(T1? t1) where T1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(4, 50), // (8,31): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F2(T2? t2) where T2 : System.Object? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(8, 31), // (8,50): error CS0702: Constraint cannot be special class 'object' // public static void F2(T2? t2) where T2 : System.Object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "System.Object?").WithArguments("object").WithLocation(8, 50) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1)", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.IsReferenceType); Assert.False(t1.IsNotNullable); Assert.Empty(t1.GetAttributes()); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T2? t2)", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.False(t2.IsReferenceType); Assert.False(t2.IsNotNullable); Assert.Empty(t2.GetAttributes()); } [Fact] public void Constraints_49() { var source = @" class B { public static void F1() where T1 : notnull { } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7_3); var expected = new[] { // (4,44): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // public static void F1() where T1 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(4, 44) }; comp.VerifyDiagnostics(expected); { var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T1 : notnull", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.IsReferenceType); Assert.True(t1.IsNotNullable); Assert.Empty(t1.GetAttributes()); } comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); comp.VerifyDiagnostics(expected .Concat(new[] { // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.3. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.3", "preview").WithLocation(1, 1), }).ToArray() ); { var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1() where T1 : notnull", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.False(t1.IsReferenceType); Assert.True(t1.IsNotNullable); Assert.Empty(t1.GetAttributes()); } } [Fact] public void Constraints_50() { var source = @" class B { public static void F1(T1? t1) where T1 : notnull { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,31): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F1(T1? t1) where T1 : notnull Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T1?").WithLocation(4, 31) ); } [Fact] public void Constraints_51() { var source = @" class B { public static void F1(T1? t1) where T1 : struct, notnull { } public static void F2(T2? t2) where T2 : notnull, struct { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints // public static void F2(T2? t2) where T2 : notnull, struct Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "struct").WithLocation(8, 59), // (4,58): error CS8713: The 'notnull' constraint must come before any other constraints // public static void F1(T1? t1) where T1 : struct, notnull Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 58) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : struct", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsValueType); Assert.True(t1.HasNotNullConstraint); Assert.True(t1.IsNotNullable); Assert.Empty(t1.GetAttributes()); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T2? t2) where T2 : struct", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.IsValueType); Assert.True(t2.HasNotNullConstraint); Assert.True(t2.IsNotNullable); Assert.Empty(t2.GetAttributes()); } [Fact] public void Constraints_52() { var source = @" class B { public static void F1(T1? t1) where T1 : class, notnull { } public static void F2(T2? t2) where T2 : notnull, class { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,57): error CS8713: The 'notnull' constraint must come before any other constraints // public static void F1(T1? t1) where T1 : class, notnull Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 57), // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints // public static void F2(T2? t2) where T2 : notnull, class Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(8, 59) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : class!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.True(t1.IsNotNullable); Assert.Empty(t1.GetAttributes()); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T2? t2) where T2 : class!", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.IsReferenceType); Assert.True(t2.IsNotNullable); Assert.Empty(t2.GetAttributes()); } [Fact] public void Constraints_53() { var source = @" class B { public static void F1(T1? t1) where T1 : class?, notnull { } public static void F2(T2? t2) where T2 : notnull, class? { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); Assert.True(((MethodSymbol)comp.SourceModule.GlobalNamespace.GetMember("B.F1")).TypeParameters[0].IsNotNullable); comp.VerifyDiagnostics( // (4,58): error CS8713: The 'notnull' constraint must come before any other constraints // public static void F1(T1? t1) where T1 : class?, notnull Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 58), // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints // public static void F2(T2? t2) where T2 : notnull, class? Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(8, 59) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : class?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.True(t1.IsNotNullable); Assert.Empty(t1.GetAttributes()); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T2? t2) where T2 : class?", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = f2.TypeParameters[0]; Assert.True(t2.IsReferenceType); Assert.True(t2.IsNotNullable); Assert.Empty(t2.GetAttributes()); } [Fact] public void Constraints_54() { var source = @" class B { public static void F1(T1? t1) where T1 : class?, B { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,31): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static void F1(T1? t1) where T1 : class?, B Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T1?").WithLocation(4, 31), // (4,58): error CS0450: 'B': cannot specify both a constraint class and the 'class' or 'struct' constraint // public static void F1(T1? t1) where T1 : class?, B Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "B").WithArguments("B").WithLocation(4, 58) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : class?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.False(t1.IsNotNullable); } [Fact] public void Constraints_55() { var source = @" interface I { void F1(TF1 x) where TF1 : TI; } class A : I { void I.F1(TF1A x) {} } class B : I { void I.F1(TF1B x) {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var af1 = (MethodSymbol)m.GlobalNamespace.GetMember("A.I.F1"); Assert.Equal("I.F1", af1.Name); Assert.Equal("I.F1", af1.MetadataName); if (isSource) { Assert.Equal("void A.I.F1(TF1A x) where TF1A : System.Object!", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void A.I.F1(TF1A x) where TF1A : System.Object!", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", af1.GetAttributes().Single().ToString()); } TypeParameterSymbol at1 = af1.TypeParameters[0]; Assert.False(at1.IsReferenceType); Assert.True(at1.IsNotNullable); if (isSource) { Assert.Empty(at1.GetAttributes()); Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(0)", at1.GetAttributes().Single().ToString()); var impl = af1.ExplicitInterfaceImplementations.Single(); Assert.Equal("void I.F1(TF1 x)", impl.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(impl.TypeParameters[0].IsNotNullable); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.I.F1"); Assert.Equal("I.F1", bf1.Name); Assert.Equal("I.F1", bf1.MetadataName); if (isSource) { Assert.Equal("void B.I.F1(TF1B x)", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void B.I.F1(TF1B x)", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", bf1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = bf1.TypeParameters[0]; Assert.False(tf1.IsReferenceType); Assert.False(tf1.IsNotNullable); if (isSource) { Assert.Empty(tf1.GetAttributes()); Assert.Equal("void I.F1(TF1 x)", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { var attributes = tf1.GetAttributes(); Assert.Equal(1, attributes.Length); Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", attributes[0].ToString()); var impl = bf1.ExplicitInterfaceImplementations.Single(); Assert.Equal("void I.F1(TF1 x)", impl.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(impl.TypeParameters[0].IsNotNullable); } } } [Fact] public void Constraints_56() { var source = @" interface I { void F1(TF1 x) where TF1 : TI; } class A : I { void I.F1(TF1A x) {} } class B : I { void I.F1(TF1B x) {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var af1 = (MethodSymbol)m.GlobalNamespace.GetMember("A.I.F1"); Assert.Equal("I.F1", af1.Name); Assert.Equal("I.F1", af1.MetadataName); if (isSource) { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : A!", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : A!", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", af1.GetAttributes().Single().ToString()); } TypeParameterSymbol at1 = af1.TypeParameters[0]; Assert.True(at1.IsReferenceType); Assert.True(at1.IsNotNullable); if (isSource) { Assert.Empty(at1.GetAttributes()); Assert.Equal("void I.F1(TF1 x) where TF1 : A!", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(0)", at1.GetAttributes().Single().ToString()); Assert.Equal("void I.F1(TF1 x) where TF1 : A", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.I.F1"); Assert.Equal("I.F1", bf1.Name); Assert.Equal("I.F1", bf1.MetadataName); if (isSource) { Assert.Equal("void B.I.F1(TF1B x) where TF1B : A?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void B.I.F1(TF1B x) where TF1B : A?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Empty(bf1.GetAttributes()); } TypeParameterSymbol tf1 = bf1.TypeParameters[0]; Assert.True(tf1.IsReferenceType); Assert.False(tf1.IsNotNullable); if (isSource) { Assert.Empty(tf1.GetAttributes()); Assert.Equal("void I.F1(TF1 x) where TF1 : A?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Empty(tf1.GetAttributes()); Assert.Equal("void I.F1(TF1 x) where TF1 : A", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } [Fact] public void Constraints_57() { var source = @" interface I { void F1(TF1 x) where TF1 : class?, TI; } class A : I { void I.F1(TF1A x) {} } class B : I { void I.F1(TF1B x) {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var af1 = (MethodSymbol)m.GlobalNamespace.GetMember("A.I.F1"); Assert.Equal("I.F1", af1.Name); Assert.Equal("I.F1", af1.MetadataName); if (isSource) { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : class?, System.Object!", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : class?, System.Object!", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } TypeParameterSymbol at1 = af1.TypeParameters[0]; Assert.True(at1.IsReferenceType); Assert.True(at1.IsNotNullable); if (isSource) { Assert.Equal("void I.F1(TF1 x) where TF1 : class?, System.Object!", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void I.F1(TF1 x) where TF1 : class?, System.Object", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.I.F1"); Assert.Equal("I.F1", bf1.Name); Assert.Equal("I.F1", bf1.MetadataName); if (isSource) { Assert.Equal("void B.I.F1(TF1B x) where TF1B : class?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void B.I.F1(TF1B x) where TF1B : class?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } TypeParameterSymbol tf1 = bf1.TypeParameters[0]; Assert.True(tf1.IsReferenceType); Assert.False(tf1.IsNotNullable); if (isSource) { Assert.Equal("void I.F1(TF1 x) where TF1 : class?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void I.F1(TF1 x) where TF1 : class?, System.Object", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } [Fact] public void Constraints_58() { var source = @" class B { public static void F1(T1? t1) where T1 : B, notnull { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,53): error CS8713: The 'notnull' constraint must come before any other constraints // public static void F1(T1? t1) where T1 : B, notnull Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 53) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : notnull, B!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.True(t1.IsNotNullable); } [Fact] public void Constraints_59() { var source = @" class B { public static void F1(T1? t1) where T1 : notnull, B? { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : notnull, B?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.True(t1.HasNotNullConstraint); Assert.True(t1.IsNotNullable); } } [Fact] public void Constraints_60() { var source = @" class B { public static void F1(T1? t1) where T1 : notnull, B { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : notnull, B!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.True(t1.IsNotNullable); } [Fact] public void Constraints_61() { var source = @" class B { public static void F1(T1? t1) where T1 : object?, B { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,50): error CS0702: Constraint cannot be special class 'object' // public static void F1(T1? t1) where T1 : object?, B Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(4, 50) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1? t1) where T1 : B!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = f1.TypeParameters[0]; Assert.True(t1.IsReferenceType); Assert.True(t1.IsNotNullable); } [Fact] public void Constraints_62() { var source = @" interface I { void F1(TF1 x) where TF1 : B?, TI; } class A : I { void I.F1(TF1A x) {} } class B : I { void I.F1(TF1B x) {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var af1 = (MethodSymbol)m.GlobalNamespace.GetMember("A.I.F1"); Assert.Equal("I.F1", af1.Name); Assert.Equal("I.F1", af1.MetadataName); if (isSource) { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : System.Object!, B?", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : System.Object!, B?", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } TypeParameterSymbol at1 = af1.TypeParameters[0]; Assert.True(at1.IsReferenceType); Assert.True(at1.IsNotNullable); if (isSource) { Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!, B?", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object, B?", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.I.F1"); Assert.Equal("I.F1", bf1.Name); Assert.Equal("I.F1", bf1.MetadataName); if (isSource) { Assert.Equal("void B.I.F1(TF1B x) where TF1B : B?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void B.I.F1(TF1B x) where TF1B : B?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } TypeParameterSymbol tf1 = bf1.TypeParameters[0]; Assert.True(tf1.IsReferenceType); Assert.False(tf1.IsNotNullable); if (isSource) { Assert.Equal("void I.F1(TF1 x) where TF1 : B?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object, B?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } [Fact] public void Constraints_63() { var source = @" interface I { void F1(TF1 x) where TF1 : TI1, TI2; } class A : I { void I.F1(TF1A x) {} } class B : I { void I.F1(TF1B x) {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var af1 = (MethodSymbol)m.GlobalNamespace.GetMember("A.I.F1"); Assert.Equal("I.F1", af1.Name); Assert.Equal("I.F1", af1.MetadataName); if (isSource) { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : System.Object!, B?", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void A.I.F1(TF1A! x) where TF1A : System.Object!, B?", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } TypeParameterSymbol at1 = af1.TypeParameters[0]; Assert.True(at1.IsReferenceType); Assert.True(at1.IsNotNullable); if (isSource) { Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!, B?", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void I.F1(TF1 x) where TF1 : B", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.I.F1"); Assert.Equal("I.F1", bf1.Name); Assert.Equal("I.F1", bf1.MetadataName); if (isSource) { Assert.Equal("void B.I.F1(TF1B x) where TF1B : B?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void B.I.F1(TF1B x) where TF1B : B?", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } TypeParameterSymbol tf1 = bf1.TypeParameters[0]; Assert.True(tf1.IsReferenceType); Assert.False(tf1.IsNotNullable); if (isSource) { Assert.Equal("void I.F1(TF1 x) where TF1 : B?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } else { Assert.Equal("void I.F1(TF1 x) where TF1 : B", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } [Fact] public void Constraints_64() { var source = @" interface I1 { void F1(); void F2() where TF2 : notnull; void F3() where TF3 : notnull; void F4() where TF4 : I3; void F5() where TF5 : I3; void F6() where TF6 : I3?; void F7() where TF7 : notnull, I3; void F8() where TF8 : notnull, I3; void F9() where TF9 : notnull, I3; void F10() where TF10 : notnull, I3?; void F11() where TF11 : notnull, I3?; void F12() where TF12 : notnull, I3?; void F13() where TF13 : notnull, I3?; } public interface I3 { } class A : I1 { public void F1() where TF1A : notnull {} public void F2() {} public void F3() where TF3A : notnull {} public void F4() where TF4A : notnull, I3 {} public void F5() where TF5A : notnull, I3? {} public void F6() where TF6A : notnull, I3? {} public void F7() where TF7A : I3 {} public void F8() where TF8A : I3? {} public void F9() where TF9A : notnull, I3 {} public void F10() where TF10A : I3 {} public void F11() where TF11A : I3? {} public void F12() where TF12A : notnull, I3 {} public void F13() where TF13A : notnull, I3? {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (25,17): warning CS8633: Nullability in constraints for type parameter 'TF1A' of method 'A.F1()' doesn't match the constraints for type parameter 'TF1' of interface method 'I1.F1()'. Consider using an explicit interface implementation instead. // public void F1() where TF1A : notnull Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("TF1A", "A.F1()", "TF1", "I1.F1()").WithLocation(25, 17), // (27,17): warning CS8633: Nullability in constraints for type parameter 'TF2A' of method 'A.F2()' doesn't match the constraints for type parameter 'TF2' of interface method 'I1.F2()'. Consider using an explicit interface implementation instead. // public void F2() Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("TF2A", "A.F2()", "TF2", "I1.F2()").WithLocation(27, 17), // (35,17): warning CS8633: Nullability in constraints for type parameter 'TF6A' of method 'A.F6()' doesn't match the constraints for type parameter 'TF6' of interface method 'I1.F6()'. Consider using an explicit interface implementation instead. // public void F6() where TF6A : notnull, I3? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F6").WithArguments("TF6A", "A.F6()", "TF6", "I1.F6()").WithLocation(35, 17), // (39,17): warning CS8633: Nullability in constraints for type parameter 'TF8A' of method 'A.F8()' doesn't match the constraints for type parameter 'TF8' of interface method 'I1.F8()'. Consider using an explicit interface implementation instead. // public void F8() where TF8A : I3? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F8").WithArguments("TF8A", "A.F8()", "TF8", "I1.F8()").WithLocation(39, 17), // (45,17): warning CS8633: Nullability in constraints for type parameter 'TF11A' of method 'A.F11()' doesn't match the constraints for type parameter 'TF11' of interface method 'I1.F11()'. Consider using an explicit interface implementation instead. // public void F11() where TF11A : I3? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F11").WithArguments("TF11A", "A.F11()", "TF11", "I1.F11()").WithLocation(45, 17) ); } [Fact] public void Constraints_65() { var source1 = @" public interface I1 { void F1(); void F2() where TF2 : notnull; void F3() where TF3 : notnull; void F4() where TF4 : I3; void F5() where TF5 : I3; void F7() where TF7 : notnull, I3; void F8() where TF8 : notnull, I3; void F9() where TF9 : notnull, I3; } public interface I3 { } "; var source2 = @" class A : I1 { public void F1() where TF1A : notnull {} public void F2() {} public void F3() where TF3A : notnull {} public void F4() where TF4A : notnull, I3 {} public void F5() where TF5A : notnull, I3? {} public void F7() where TF7A : I3 {} public void F8() where TF8A : I3? {} public void F9() where TF9A : notnull, I3 {} } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); foreach (var reference in new[] { comp1.ToMetadataReference(), comp1.EmitToImageReference() }) { var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { reference }); comp2.VerifyDiagnostics( // (6,17): warning CS8633: Nullability in constraints for type parameter 'TF2A' of method 'A.F2()' doesn't match the constraints for type parameter 'TF2' of interface method 'I1.F2()'. Consider using an explicit interface implementation instead. // public void F2() Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F2").WithArguments("TF2A", "A.F2()", "TF2", "I1.F2()").WithLocation(6, 17), // (16,17): warning CS8633: Nullability in constraints for type parameter 'TF8A' of method 'A.F8()' doesn't match the constraints for type parameter 'TF8' of interface method 'I1.F8()'. Consider using an explicit interface implementation instead. // public void F8() where TF8A : I3? Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F8").WithArguments("TF8A", "A.F8()", "TF8", "I1.F8()").WithLocation(16, 17) ); } string il = @" .class interface public abstract auto ansi I1 { .method public hidebysig newslot abstract virtual instance void F1() cil managed { } // end of method I1::F1 } // end of class I1"; string source3 = @" class A : I1 { public void F1() where TF1A : notnull {} } "; var comp3 = CreateCompilationWithIL(new[] { source3 }, il, options: WithNonNullTypesTrue()); comp3.VerifyDiagnostics(); } [Fact] public void Constraints_66() { var source1 = @" public interface I1 { void F1(); void F2() where TF2 : notnull; void F3() where TF3 : notnull; void F4() where TF4 : I3; void F7() where TF7 : notnull, I3; void F9() where TF9 : notnull, I3; void F10() where TF10 : notnull, I3?; void F12() where TF12 : notnull, I3?; } public interface I3 { } "; var source2 = @" class A : I1 { public void F1() where TF1A : notnull {} public void F2() {} public void F3() where TF3A : notnull {} public void F4() where TF4A : notnull, I3 {} public void F7() where TF7A : I3 {} public void F9() where TF9A : notnull, I3 {} public void F10() where TF10A : I3 {} public void F12() where TF12A : notnull, I3 {} } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesTrue()); foreach (var reference in new[] { comp1.ToMetadataReference(), comp1.EmitToImageReference() }) { var comp2 = CreateCompilation(source2, options: WithNonNullTypes(NullableContextOptions.Warnings), references: new[] { reference }); comp2.VerifyDiagnostics( // (4,17): warning CS8633: Nullability in constraints for type parameter 'TF1A' of method 'A.F1()' doesn't match the constraints for type parameter 'TF1' of interface method 'I1.F1()'. Consider using an explicit interface implementation instead. // public void F1() where TF1A : notnull Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation, "F1").WithArguments("TF1A", "A.F1()", "TF1", "I1.F1()").WithLocation(4, 17) ); } } [Fact] public void Constraints_67() { var source = @" class A { public void F1(object x1, TF1 y1, TF1 z1 ) where TF1 : notnull { y1.ToString(); x1 = z1; } public void F2(object x2, TF2 y2, TF2 z2 ) where TF2 : class { y2.ToString(); x2 = z2; } public void F3(object x3, TF3 y3, TF3 z3 ) where TF3 : class? { y3.ToString(); x3 = z3; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,9): warning CS8602: Dereference of a possibly null reference. // y3.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y3").WithLocation(18, 9), // (19,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x3 = z3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "z3").WithLocation(19, 14) ); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_68() { var source = @" #nullable enable class A { } class C where T : A { C M(C c1) { return c1; } } "; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (6,11): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // C M(C c1) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("C", "A", "T", "A?").WithLocation(6, 11), // (6,19): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // C M(C c1) Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "c1").WithArguments("C", "A", "T", "A?").WithLocation(6, 19)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_69() { var source = @" #nullable enable class C where T : notnull { } interface I { C Property { get; } // 1 C Method(C p); // 2 } class C2 : I { public C Field = new C(); // 3 C Property => Field; // 4 C Method(C p) => Field; // 5 C I.Property => Field; // 6 C I.Method(C p) => Field; // 7 } delegate C D(C p); // 8 "; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (6,16): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C Property { get; } // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Property").WithArguments("C", "T", "object?").WithLocation(6, 16), // (7,16): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C Method(C p); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Method").WithArguments("C", "T", "object?").WithLocation(7, 16), // (7,34): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C Method(C p); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("C", "T", "object?").WithLocation(7, 34), // (11,23): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // public C Field = new C(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Field").WithArguments("C", "T", "object?").WithLocation(11, 23), // (11,37): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // public C Field = new C(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(11, 37), // (12,16): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C Property => Field; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Property").WithArguments("C", "T", "object?").WithLocation(12, 16), // (13,16): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C Method(C p) => Field; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Method").WithArguments("C", "T", "object?").WithLocation(13, 16), // (13,34): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C Method(C p) => Field; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("C", "T", "object?").WithLocation(13, 34), // (15,18): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C I.Property => Field; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Property").WithArguments("C", "T", "object?").WithLocation(15, 18), // (16,18): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C I.Method(C p) => Field; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "Method").WithArguments("C", "T", "object?").WithLocation(16, 18), // (16,36): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // C I.Method(C p) => Field; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("C", "T", "object?").WithLocation(16, 36), // (19,12): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // delegate C D(C p); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(19, 12), // (19,25): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // delegate C D(C p); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(19, 25)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_70() { var source = @" #nullable enable class C where T : class { } interface I { C Property { get; } // 1 C Method(C p); // 2 } class C2 : I { public C Field = new C(); // 3 C Property => Field; // 4 C Method(C p) => Field; // 5 C I.Property => Field; // 6 C I.Method(C p) => Field; // 7 } delegate C D(C p); // 8 "; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (6,16): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C Property { get; } // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Property").WithArguments("C", "T", "object?").WithLocation(6, 16), // (7,16): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C Method(C p); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Method").WithArguments("C", "T", "object?").WithLocation(7, 16), // (7,34): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C Method(C p); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "p").WithArguments("C", "T", "object?").WithLocation(7, 34), // (11,23): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // public C Field = new C(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Field").WithArguments("C", "T", "object?").WithLocation(11, 23), // (11,37): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // public C Field = new C(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(11, 37), // (12,16): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C Property => Field; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Property").WithArguments("C", "T", "object?").WithLocation(12, 16), // (13,16): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C Method(C p) => Field; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Method").WithArguments("C", "T", "object?").WithLocation(13, 16), // (13,34): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C Method(C p) => Field; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "p").WithArguments("C", "T", "object?").WithLocation(13, 34), // (15,18): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C I.Property => Field; // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Property").WithArguments("C", "T", "object?").WithLocation(15, 18), // (16,18): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C I.Method(C p) => Field; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "Method").WithArguments("C", "T", "object?").WithLocation(16, 18), // (16,36): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // C I.Method(C p) => Field; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "p").WithArguments("C", "T", "object?").WithLocation(16, 36), // (19,12): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // delegate C D(C p); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(19, 12), // (19,25): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // delegate C D(C p); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(19, 25)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_71() { var source = @" #nullable enable #pragma warning disable 8019 using static C1; using static C1; // 1 using static C2; using static C2; using static C3; // 2 using static C3; using static C4; using static C4; class A { } static class C1 where T : A { } static class C2 where T : A? { } static class C3 where T : class { } static class C4 where T : class? { } "; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (6,14): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C1'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // using static C1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "C1").WithArguments("C1", "A", "T", "A?").WithLocation(6, 14), // (10,14): warning CS8634: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C3'. Nullability of type argument 'A?' doesn't match 'class' constraint. // using static C3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "C3").WithArguments("C3", "T", "A?").WithLocation(10, 14)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_72() { var source = @" #nullable enable #pragma warning disable 8019 using D1 = C1; using D2 = C1; // 1 using D3 = C2; using D4 = C2; using D5 = C3; // 2 using D6 = C3; using D7 = C4; using D8 = C4; class A { } static class C1 where T : A { } static class C2 where T : A? { } static class C3 where T : class { } static class C4 where T : class? { } "; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (6,7): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C1'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // using D2 = C1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "D2").WithArguments("C1", "A", "T", "A?").WithLocation(6, 7), // (10,7): warning CS8634: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C3'. Nullability of type argument 'A?' doesn't match 'class' constraint. // using D6 = C3; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "D6").WithArguments("C3", "T", "A?").WithLocation(10, 7)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_73() { var source = @" #nullable enable class C { void M1((string, string?) p) { } // 1 void M2((string, string) p) { } void M3(C<(string, string?)> p) { } // 2 void M4(C<(string, string)> p) { } } "; var compilation = CreateCompilation(new[] { Tuple2NonNullable, source }, targetFramework: TargetFramework.Mscorlib46); compilation.VerifyDiagnostics( // (4,31): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // void M1((string, string?) p) { } // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(4, 31), // (6,34): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // void M3(C<(string, string?)> p) { } // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(6, 34)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_74() { var source = @" #nullable enable class C where T : notnull { } class D1 { D1((string, string?) p) { } // 1 D1(C<(string, string?)> p) { } // 2 D1(C p) { } // 3 } class D2 { D2((string, string) p) { } D2(C<(string, string)> p) { } D2(C p) { } } "; var compilation = CreateCompilation(new[] { Tuple2NonNullable, source }, targetFramework: TargetFramework.Mscorlib46); compilation.VerifyDiagnostics( // (5,26): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // D1((string, string?) p) { } // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(5, 26), // (6,29): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // D1(C<(string, string?)> p) { } // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(6, 29), // (7,19): warning CS8714: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // D1(C p) { } // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "p").WithArguments("C", "T", "string?").WithLocation(7, 19)); } [Fact] [WorkItem(32953, "https://github.com/dotnet/roslyn/issues/32953")] public void Constraints_75() { var source = @" #nullable enable class C where T : notnull { } class D1 { public static implicit operator D1(C c) => new D1(); public static implicit operator C(D1 D1) => new C(); } class D2 { public static implicit operator D2(C c) => new D2(); // 1 public static implicit operator C(D2 D2) => new C(); // 2, 3 } "; var compilation = CreateCompilation(source, targetFramework: TargetFramework.Mscorlib46); compilation.VerifyDiagnostics( // (9,51): warning CS8714: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // public static implicit operator D2(C c) => new D2(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "c").WithArguments("C", "T", "string?").WithLocation(9, 51), // (10,37): warning CS8714: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // public static implicit operator C(D2 D2) => new C(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "C").WithArguments("C", "T", "string?").WithLocation(10, 37), // (10,64): warning CS8714: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // public static implicit operator C(D2 D2) => new C(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("C", "T", "string?").WithLocation(10, 64)); } [Fact] [WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")] public void Constraints_76() { var source = @" #nullable enable #pragma warning disable 8600, 219 class C { void TupleLiterals() { string s1 = string.Empty; string? s2 = null; var t1 = (s1, s1); var t2 = (s1, s2); // 1 var t3 = (s2, s1); // 2 var t4 = (s2, s2); // 3, 4 var t5 = ((string)null, s1); // 5 var t6 = ((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null); // 6, 7, 8 } } "; var compilation = CreateCompilation(new[] { Tuple2NonNullable, TupleRestNonNullable, source }, targetFramework: TargetFramework.Mscorlib46); compilation.VerifyDiagnostics( // (9,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t2 = (s1, s2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "(s1, s2)").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(9, 18), // (10,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t3 = (s2, s1); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "(s2, s1)").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(10, 18), // (11,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t4 = (s2, s2); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "(s2, s2)").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(11, 18), // (11,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t4 = (s2, s2); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "(s2, s2)").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(11, 18), // (12,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t5 = ((string)null, s1); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "((string)null, s1)").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(12, 18), // (13,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t6 = ((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null); // 6, 7, 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null)").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(13, 18), // (13,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t6 = ((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null); // 6, 7, 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null)").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(13, 18), // (13,18): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // var t6 = ((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null); // 6, 7, 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "((string)null, s1, s1, s1, s1, s1, s1, (string)null, (string)null)").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(13, 18) ); } [Fact] [WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")] public void Constraints_77() { var source = @" using System; #nullable enable #pragma warning disable 168 class C { void TupleTypes() { (string?, string) t1; (string?, string, string, string, string, string, string, string, string?) t2; Type t3 = typeof((string?, string)); Type t4 = typeof((string?, string, string, string, string, string, string, string, string?)); } } "; var compilation = CreateCompilation(new[] { Tuple2NonNullable, TupleRestNonNullable, source }, targetFramework: TargetFramework.Mscorlib46); compilation.VerifyDiagnostics( // (7,10): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // (string?, string) t1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(7, 10), // (8,10): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // (string?, string, string, string, string, string, string, string, string?) t2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(8, 10), // (8,75): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // (string?, string, string, string, string, string, string, string, string?) t2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(8, 75), // (9,27): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // Type t3 = typeof((string?, string)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(9, 27), // (10,27): warning CS8714: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // Type t4 = typeof((string?, string, string, string, string, string, string, string, string?)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("System.ValueTuple", "T1", "string?").WithLocation(10, 27), // (10,92): warning CS8714: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // Type t4 = typeof((string?, string, string, string, string, string, string, string, string?)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("System.ValueTuple", "T2", "string?").WithLocation(10, 92) ); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33011")] [WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")] public void Constraints_78() { var source = @" #nullable enable #pragma warning disable 8600 class C { void Deconstruction() { string s1; string? s2; C c = new C(); (s1, s1) = ("""", """"); (s2, s1) = ((string)null, """"); var v1 = (s2, s1) = ((string)null, """"); // 1 var v2 = (s1, s1) = ((string)null, """"); // 2 (s2, s1) = c; (string? s3, string s4) = c; var v2 = (s2, s1) = c; // 3 } public void Deconstruct(out string? s1, out string s2) { s1 = null; s2 = string.Empty; } } "; var compilation = CreateCompilation(new[] { Tuple2NonNullable, source }, targetFramework: TargetFramework.Mscorlib46); compilation.VerifyDiagnostics( ); } [Fact] [WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")] public void Constraints_79() { var source = @" using System; #nullable enable #pragma warning disable 168 class C { void TupleTypes() { (string?, string) t1; Type t2 = typeof((string?, string)); } } "; var compilation = CreateCompilation(new[] { Tuple2NonNullable, TupleRestNonNullable, source }, targetFramework: TargetFramework.Mscorlib46, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); compilation.VerifyDiagnostics( // (3,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(3, 2), // (4,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(4, 2), // (4,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable enable Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(4, 2), // (6,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T1 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(6, 20), // (7,16): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // (string?, string) t1; Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(7, 16), // (7,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T1 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(7, 20), // (7,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T2 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(7, 20), // (8,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T2 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(8, 20), // (8,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T3 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(8, 20), // (8,33): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // Type t2 = typeof((string?, string)); Diagnostic(ErrorCode.ERR_FeatureInPreview, "?").WithArguments("nullable reference types").WithLocation(8, 33), // (9,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T4 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(9, 20), // (10,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T5 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(10, 20), // (11,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T6 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(11, 20), // (12,20): error CS8652: The feature 'notnull generic type constraint' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // where T7 : notnull Diagnostic(ErrorCode.ERR_FeatureInPreview, "notnull").WithArguments("notnull generic type constraint").WithLocation(12, 20)); } [Fact] public void Constraints_80() { var source1 = @" #nullable disable public interface I1 { void F1(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1()", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } var source2 = @" #nullable disable public interface I1 { void F1() where TF2 : class; } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator2, symbolValidator: symbolValidator2); void symbolValidator2(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF2 : class", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); foreach (TypeParameterSymbol tf1 in f1.TypeParameters) { Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } } [Fact] public void Constraints_81() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : new(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : new()", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_82() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : class; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : class", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_83() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : struct; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : struct", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_84() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : unmanaged; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : unmanaged", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_85() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : I1; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : I1", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_86() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : class?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (5,37): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void F1() where TF1 : class?; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 37) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetMember("I1"); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : class?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_87() { var source1 = @" #nullable disable public interface I1 { void F1() where TF1 : I1?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (5,34): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void F1() where TF1 : I1?; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 34) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : I1?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_88() { var source1 = @" #nullable enable public interface I1 { void F1(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetMember("I1"); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1()", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } var source2 = @" #nullable enable public interface I1 { void F1() where TF1 : class?; } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator2, symbolValidator: symbolValidator2); void symbolValidator2(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetMember("I1"); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : class?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); foreach (TypeParameterSymbol tf1 in f1.TypeParameters) { Assert.False(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } } [Fact] public void Constraints_89() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : new(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetMember("I1"); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : new()", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_90() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : class; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetMember("I1"); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", i1.GetAttributes().Single().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : class!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_91() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : struct; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : struct", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_92() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : unmanaged; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : unmanaged", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_93() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : I1; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : I1!", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_94() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : class?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetMember("I1"); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : class?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_95() { var source1 = @" #nullable enable public interface I1 { void F1() where TF1 : I1?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("I1.F1"); Assert.Equal("void I1.F1() where TF1 : I1?", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = f1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_96() { var source1 = @" #nullable disable public interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } var source2 = @" #nullable disable public interface I1 where TF2 : class { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator2, symbolValidator: symbolValidator2); void symbolValidator2(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF2 : class", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); foreach (TypeParameterSymbol tf1 in i1.TypeParameters) { Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } } [Fact] public void Constraints_97() { var source1 = @" #nullable disable public interface I1 where TF1 : new() { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : new()", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_98() { var source1 = @" #nullable disable public interface I1 where TF1 : class { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : class", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_99() { var source1 = @" #nullable disable public interface I1 where TF1 : struct { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : struct", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_100() { var source1 = @" #nullable disable public interface I1 where TF1 : unmanaged { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : unmanaged", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_101() { var source1 = @" #nullable disable public interface I1 where TF1 : I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_102() { var source1 = @" #nullable disable public interface I1 where TF1 : class? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (3,43): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public interface I1 where TF1 : class? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 43) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : class?", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_103() { var source1 = @" #nullable disable public interface I1 where TF1 : I1? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (3,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public interface I1 where TF1 : I1? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 45) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : I1?", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.Empty(tf1.GetAttributes()); } } [Fact] public void Constraints_104() { var source1 = @" #nullable enable public interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } var source2 = @" #nullable enable public interface I1 where TF1 : class? { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator2, symbolValidator: symbolValidator2); void symbolValidator2(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : class?", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } foreach (TypeParameterSymbol tf1 in i1.TypeParameters) { Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } } [Fact] public void Constraints_105() { var source1 = @" #nullable enable public interface I1 where TF1 : new() { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : new()", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_106() { var source1 = @" #nullable enable public interface I1 where TF1 : class { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : class!", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_107() { var source1 = @" #nullable enable public interface I1 where TF1 : struct { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : struct", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_108() { var source1 = @" #nullable enable public interface I1 where TF1 : unmanaged { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : unmanaged", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_109() { var source1 = @" #nullable enable public interface I1 where TF1 : I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : I1!", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_110() { var source1 = @" #nullable enable public interface I1 where TF1 : class? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : class?", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_111() { var source1 = @" #nullable enable public interface I1 where TF1 : I1? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1 where TF1 : I1?", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_112() { var source1 = @" #nullable disable #nullable enable warnings partial interface I1 { } partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.Null(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_113() { var source1 = @" #nullable enable partial interface I1 { } partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_114() { var source1 = @"#nullable disable #nullable enable warnings partial interface I1 { } #nullable enable partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_115() { var source1 = @" #nullable enable partial interface I1 { } #nullable disable #nullable enable warnings partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator1, symbolValidator: symbolValidator1); void symbolValidator1(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var i1 = m.GlobalNamespace.GetTypeMember("I1"); Assert.Equal("I1", i1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); if (isSource) { Assert.Empty(i1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(2)", i1.GetAttributes().Single().ToString()); } TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var attributes = tf1.GetAttributes(); Assert.Empty(attributes); } } [Fact] public void Constraints_116() { var source1 = @"#nullable disable #nullable enable warnings partial interface I1 { } partial interface I1 where TF1 : notnull { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.HasNotNullConstraint); Assert.True(tf1.IsNotNullable); var source2 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : new() { } partial interface I1 where TF1 : notnull, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'TF1' // partial interface I1 where TF1 : new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "TF1").WithLocation(3, 19) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.HasNotNullConstraint); Assert.Null(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : notnull, new() { } partial interface I1 where TF1 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (3,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'TF1' // partial interface I1 where TF1 : notnull, new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "TF1").WithLocation(3, 19) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.True(tf1.HasNotNullConstraint); Assert.True(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); } [Fact] public void Constraints_117() { var source1 = @" #nullable enable partial interface I1 { } partial interface I1 where TF1 : notnull { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.HasNotNullConstraint); Assert.True(tf1.IsNotNullable); var source2 = @" #nullable enable partial interface I1 where TF1 : new() { } partial interface I1 where TF1 : notnull, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'TF1' // partial interface I1 where TF1 : new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "TF1").WithLocation(3, 19) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.HasNotNullConstraint); Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); } [Fact] public void Constraints_118() { var source1 = @" #nullable disable #nullable enable warnings partial interface I1 { } #nullable enable partial interface I1 where TF1 : notnull { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var source2 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : new() { } #nullable enable partial interface I1 where TF1 : notnull, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'TF1' // partial interface I1 where TF1 : new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "TF1").WithLocation(3, 19) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.HasNotNullConstraint); Assert.Null(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @" #nullable enable partial interface I1 where TF1 : notnull, new() { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (3,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'TF1' // partial interface I1 where TF1 : notnull, new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "TF1").WithLocation(3, 19) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.True(tf1.HasNotNullConstraint); Assert.True(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); } [Fact] public void Constraints_119() { var source1 = @" #nullable enable partial interface I1 { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : notnull { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.True(tf1.IsNotNullable); var source2 = @" #nullable enable partial interface I1 where TF1 : new() { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : notnull, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'TF1' // partial interface I1 where TF1 : new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "TF1").WithLocation(3, 19) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); } [Fact] public void Constraints_120() { var source1 = @"#nullable disable #nullable enable warnings partial interface I1 { } partial interface I1 where TF1 : object? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (7,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 39), // (7,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 45) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : new() { } partial interface I1 where TF1 : object?, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (7,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 39), // (7,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 45) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @"#nullable disable #nullable enable warnings partial interface I1 where TF2 : new() { } partial interface I1 where TF1 : object? where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (7,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 44), // (7,50): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 50) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.Null(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] public void Constraints_121() { var source1 = @" #nullable enable partial interface I1 { } partial interface I1 where TF1 : object? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (7,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 39) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @" #nullable enable partial interface I1 where TF1 : new() { } partial interface I1 where TF1 : object?, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (7,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 39) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @" #nullable enable partial interface I1 where TF2 : new() { } partial interface I1 where TF1 : object? where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (7,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 44) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.False(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_122() { var source1 = @"#nullable disable #nullable enable warnings partial interface I1 { } #nullable enable partial interface I1 where TF1 : object? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (8,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 39) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : new() { } #nullable enable partial interface I1 where TF1 : object?, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (8,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 39) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @"#nullable disable #nullable enable warnings partial interface I1 where TF2 : new() { } #nullable enable partial interface I1 where TF1 : object? where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (8,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 44) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.False(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_123() { var source1 = @" #nullable enable partial interface I1 { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : object? { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (8,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 39), // (8,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 45) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @" #nullable enable partial interface I1 where TF1 : new() { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : object?, new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (8,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 39), // (8,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 45) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @" #nullable enable partial interface I1 where TF2 : new() { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : object? where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (8,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 44), // (8,50): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 50) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.False(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] public void Constraints_124() { var source1 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : object? { } partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39), // (3,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 45) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : object?, new() { } partial interface I1 where TF1 : new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39), // (3,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 45) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : object? where TF2 : new() { } partial interface I1 where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (3,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 44), // (3,50): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 50) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.Null(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] public void Constraints_125() { var source1 = @" #nullable enable partial interface I1 where TF1 : object? { } partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @" #nullable enable partial interface I1 where TF1 : object?, new() { } partial interface I1 where TF1 : new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @" #nullable enable partial interface I1 where TF1 : object? where TF2 : new() { } partial interface I1 where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (3,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 44) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.False(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_126() { var source1 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : object? { } #nullable enable partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39), // (3,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 45) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : object?, new() { } #nullable enable partial interface I1 where TF1 : new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39), // (3,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 45) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @"#nullable disable #nullable enable warnings partial interface I1 where TF1 : object? where TF2 : new() { } #nullable enable partial interface I1 where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (3,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 44), // (3,50): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 50) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.False(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_127() { var source1 = @" #nullable enable partial interface I1 where TF1 : object? { } #nullable disable #nullable enable warnings partial interface I1 { } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39) ); var i1 = comp1.GlobalNamespace.GetTypeMember("I1"); TypeParameterSymbol tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); var source2 = @" #nullable enable partial interface I1 where TF1 : object?, new() { } #nullable disable #nullable enable warnings partial interface I1 where TF1 : new() { } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics( // (3,39): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object?, new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 39) ); i1 = comp2.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); Assert.True(tf1.HasConstructorConstraint); var source3 = @" #nullable enable partial interface I1 where TF1 : object? where TF2 : new() { } #nullable disable #nullable enable warnings partial interface I1 where TF2 : new() { } "; var comp3 = CreateCompilation(source3); comp3.VerifyDiagnostics( // (3,44): error CS0702: Constraint cannot be special class 'object' // partial interface I1 where TF1 : object? where TF2 : new() Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(3, 44) ); i1 = comp3.GlobalNamespace.GetTypeMember("I1"); tf1 = i1.TypeParameters[0]; Assert.False(tf1.IsNotNullable); TypeParameterSymbol tf2 = i1.TypeParameters[1]; Assert.False(tf2.IsNotNullable); Assert.True(tf2.HasConstructorConstraint); } [Fact] public void Constraints_128() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1(); partial void M1() { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); } [Fact] public void Constraints_129() { var source1 = @" partial class A { #nullable enable partial void M1(); partial void M1() { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_130() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1(); #nullable enable partial void M1() { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.Null(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); var source2 = @" partial class A { #nullable enable partial void M1() { } #nullable disable #nullable enable warnings partial void M1(); } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics(); m1 = comp2.GlobalNamespace.GetMember("A.M1"); Assert.Null(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_131() { var source1 = @" partial class A { #nullable enable partial void M1(); #nullable disable #nullable enable warnings partial void M1() { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.Null(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); var source2 = @"#nullable disable partial class A { #nullable enable warnings partial void M1() { } #nullable enable partial void M1(); } "; var comp2 = CreateCompilation(source2); comp2.VerifyDiagnostics(); m1 = comp2.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.Null(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] public void Constraints_132() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1(); partial void M1() where TF1 : notnull { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_133() { var source1 = @" partial class A { #nullable enable partial void M1(); partial void M1() where TF1 : notnull { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (7,14): warning CS8667: Partial method declarations of 'A.M1()' have inconsistent nullability in constraints for type parameter 'TF1' // partial void M1() where TF1 : notnull Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation, "M1").WithArguments("A.M1()", "TF1").WithLocation(7, 14) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.True(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_134() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1(); #nullable enable partial void M1() where TF1 : notnull { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.Null(m1.TypeParameters[0].IsNotNullable); Assert.True(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_135() { var source1 = @" partial class A { #nullable enable partial void M1(); #nullable disable #nullable enable warnings partial void M1() where TF1 : notnull { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (8,14): warning CS8667: Partial method declarations of 'A.M1()' have inconsistent nullability in constraints for type parameter 'TF1' // partial void M1() where TF1 : notnull Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation, "M1").WithArguments("A.M1()", "TF1").WithLocation(8, 14) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.True(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_136() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1(); partial void M1() where TF1 : object? { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (7,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 36), // (7,42): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1() where TF1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 42) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.Null(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_137() { var source1 = @" partial class A { #nullable enable partial void M1(); partial void M1() where TF1 : object? { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (7,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(7, 36) ); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_138() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1(); #nullable enable partial void M1() where TF1 : object? { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (8,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 36) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.Null(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] public void Constraints_139() { var source1 = @" partial class A { #nullable enable partial void M1(); #nullable disable #nullable enable warnings partial void M1() where TF1 : object? { } } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (8,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(8, 36), // (8,42): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1() where TF1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 42) ); } [Fact] public void Constraints_140() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1() { } partial void M1(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); } [Fact] public void Constraints_141() { var source1 = @" partial class A { #nullable enable partial void M1() { } partial void M1(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_142() { var source1 = @"#nullable disable partial class A { #nullable enable warnings partial void M1() { } #nullable enable partial void M1(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.Null(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_143() { var source1 = @" partial class A { #nullable enable partial void M1() { } #nullable disable #nullable enable warnings partial void M1(); } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.Null(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] public void Constraints_144() { var source1 = @" partial class A { #nullable disable #nullable enable warnings partial void M1() { } partial void M1() where TF1 : notnull; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_145() { var source1 = @" partial class A { #nullable enable partial void M1() { } partial void M1() where TF1 : notnull; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (5,14): warning CS8667: Partial method declarations of 'A.M1()' have inconsistent nullability in constraints for type parameter 'TF1' // partial void M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation, "M1").WithArguments("A.M1()", "TF1").WithLocation(5, 14) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.True(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_146() { var source1 = @"#nullable disable partial class A { #nullable enable warnings partial void M1() { } #nullable enable partial void M1() where TF1 : notnull; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics(); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.True(m1.TypeParameters[0].IsNotNullable); Assert.Null(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_147() { var source1 = @" partial class A { #nullable enable partial void M1() { } #nullable disable #nullable enable warnings partial void M1() where TF1 : notnull; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (5,14): warning CS8667: Partial method declarations of 'A.M1()' have inconsistent nullability in constraints for type parameter 'TF1' // partial void M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation, "M1").WithArguments("A.M1()", "TF1").WithLocation(5, 14) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.True(m1.TypeParameters[0].IsNotNullable); Assert.False(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_148() { var source1 = @"#nullable disable partial class A { #nullable enable warnings partial void M1() { } partial void M1() where TF1 : object?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (9,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object?; Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(9, 36), // (9,42): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1() where TF1 : object?; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 42) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.Null(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] public void Constraints_149() { var source1 = @" partial class A { #nullable enable partial void M1() { } partial void M1() where TF1 : object?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (9,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object?; Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(9, 36) ); } [Fact] [WorkItem(30229, "https://github.com/dotnet/roslyn/issues/30229")] public void Constraints_150() { var source1 = @"#nullable disable partial class A { #nullable enable warnings partial void M1() { } #nullable enable partial void M1() where TF1 : object?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (10,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object?; Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(10, 36) ); var m1 = comp1.GlobalNamespace.GetMember("A.M1"); Assert.False(m1.TypeParameters[0].IsNotNullable); Assert.Null(m1.PartialImplementationPart.TypeParameters[0].IsNotNullable); } [Fact] public void Constraints_151() { var source1 = @" partial class A { #nullable enable partial void M1() { } #nullable disable #nullable enable warnings partial void M1() where TF1 : object?; } "; var comp1 = CreateCompilation(source1); comp1.VerifyDiagnostics( // (10,36): error CS0702: Constraint cannot be special class 'object' // partial void M1() where TF1 : object?; Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(10, 36), // (10,42): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // partial void M1() where TF1 : object?; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 42) ); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/34798")] public void Constraints_152() { var source = @" class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } class B : A { public override void F1(T11? t1) where T11 : class { } public override void F2(T22 t2) { } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T11? t1) where T11 : class", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t11.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(1)", t11.GetAttributes().Single().ToString()); } var af1 = bf1.OverriddenMethod; Assert.Equal("void A.F1(T1? t1) where T1 : class", af1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t1 = af1.TypeParameters[0]; Assert.False(t1.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t1.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(1)", t1.GetAttributes().Single().ToString()); } var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T22 t2) where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t22.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t22.GetAttributes().Single().ToString()); } var af2 = bf2.OverriddenMethod; Assert.Equal("void A.F2(T2 t2) where T2 : class?", af2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t2 = af2.TypeParameters[0]; Assert.True(t2.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t2.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", t2.GetAttributes().Single().ToString()); } } } [Fact] public void Constraints_153() { var source1 = @" public class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var source2 = @" class B : A { public override void F1(T11? t1) where T11 : class { } public override void F2(T22 t2) { } } "; var comp2 = CreateCompilation(new[] { source2 }, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var b = m.GlobalNamespace.GetMember("B"); if (isSource) { Assert.Empty(b.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", b.GetAttributes().First().ToString()); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T11? t1) where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T22 t2) where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t22.GetAttributes()); } else { CSharpAttributeData nullableAttribute = t22.GetAttributes().Single(); Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", nullableAttribute.ToString()); Assert.Same(m, nullableAttribute.AttributeClass.ContainingModule); Assert.Equal(Accessibility.Internal, nullableAttribute.AttributeClass.DeclaredAccessibility); } } } [Fact] public void Constraints_154() { var source1 = @" public class A { public virtual void F1(T1? t1) where T1 : class { } public virtual void F2(T2 t2) where T2 : class? { } } "; var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue()); var comp2 = CreateCompilation(NullableAttributeDefinition); var source3 = @" class B : A { public override void F1(T11? t1) where T11 : class { } public override void F2(T22 t2) { } } "; var comp3 = CreateCompilation(new[] { source3 }, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference(), comp2.EmitToImageReference() }, parseOptions: TestOptions.Regular8); CompileAndVerify(comp3, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { bool isSource = !(m is PEModuleSymbol); var b = m.GlobalNamespace.GetMember("B"); if (isSource) { Assert.Empty(b.GetAttributes()); } else { Assert.Equal("System.Runtime.CompilerServices.NullableContextAttribute(1)", b.GetAttributes().First().ToString()); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T11? t1) where T11 : class!", bf1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t11 = bf1.TypeParameters[0]; Assert.False(t11.ReferenceTypeConstraintIsNullable); Assert.Empty(t11.GetAttributes()); var bf2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T22 t2) where T22 : class?", bf2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol t22 = bf2.TypeParameters[0]; Assert.True(t22.ReferenceTypeConstraintIsNullable); if (isSource) { Assert.Empty(t22.GetAttributes()); } else { CSharpAttributeData nullableAttribute = t22.GetAttributes().Single(); Assert.Equal("System.Runtime.CompilerServices.NullableAttribute(2)", nullableAttribute.ToString()); Assert.NotEqual(m, nullableAttribute.AttributeClass.ContainingModule); } } } [Fact] public void DynamicConstraint_01() { var source = @" class B { public static void F1(T1 t1) where T1 : dynamic { } public static void F2(T2 t2) where T2 : B { } }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (4,49): error CS1967: Constraint cannot be the dynamic type // public static void F1(T1 t1) where T1 : dynamic Diagnostic(ErrorCode.ERR_DynamicTypeAsBound, "dynamic").WithLocation(4, 49), // (8,49): error CS1968: Constraint cannot be a dynamic type 'B' // public static void F2(T2 t2) where T2 : B Diagnostic(ErrorCode.ERR_ConstructedDynamicTypeAsBound, "B").WithArguments("B").WithLocation(8, 49) ); var m = comp.SourceModule; var f1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F1"); Assert.Equal("void B.F1(T1 t1)", f1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); var f2 = (MethodSymbol)m.GlobalNamespace.GetMember("B.F2"); Assert.Equal("void B.F2(T2 t2)", f2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } [Fact] [WorkItem(36276, "https://github.com/dotnet/roslyn/issues/36276")] public void DynamicConstraint_02() { var source1 = @" #nullable enable class Test1 { public virtual void M1() where S : T { } } class Test2 : Test1 { public override void M1() { } void Test() { base.M1(); this.M1(); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (18,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test1.M1()'. Nullability of type argument 'object?' doesn't match constraint type 'object'. // base.M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "base.M1").WithArguments("Test1.M1()", "object", "S", "object?").WithLocation(18, 9), // (19,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test2.M1()'. Nullability of type argument 'object?' doesn't match constraint type 'object'. // this.M1(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "this.M1").WithArguments("Test2.M1()", "object", "S", "object?").WithLocation(19, 9) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1() where S : System.Object!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); var baseM1 = m1.OverriddenMethod; Assert.Equal("void Test1.M1() where S : System.Object!", baseM1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(baseM1.TypeParameters[0].IsNotNullable); } } [Fact] [WorkItem(36276, "https://github.com/dotnet/roslyn/issues/36276")] public void DynamicConstraint_03() { var source1 = @" #nullable disable class Test1 { public virtual void M1() where S : T { } } class Test2 : Test1 { public override void M1() { } void Test() { #nullable enable base.M1(); this.M1(); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1()", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); var baseM1 = m1.OverriddenMethod; Assert.Equal("void Test1.M1()", baseM1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(baseM1.TypeParameters[0].IsNotNullable); } } [Fact] public void DynamicConstraint_04() { var source1 = @" #nullable enable class Test1 { public virtual void M1() where S : T { } } class Test2 : Test1> { public override void M1() { } void Test() { base.M1>(); this.M1>(); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (18,9): warning CS8631: The type 'Test1' cannot be used as type parameter 'S' in the generic type or method 'Test1>.M1()'. Nullability of type argument 'Test1' doesn't match constraint type 'Test1'. // base.M1>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "base.M1>").WithArguments("Test1>.M1()", "Test1", "S", "Test1").WithLocation(18, 9), // (19,9): warning CS8631: The type 'Test1' cannot be used as type parameter 'S' in the generic type or method 'Test2.M1()'. Nullability of type argument 'Test1' doesn't match constraint type 'Test1'. // this.M1>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "this.M1>").WithArguments("Test2.M1()", "Test1", "S", "Test1").WithLocation(19, 9) ); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1() where S : Test1!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); var baseM1 = m1.OverriddenMethod; Assert.Equal("void Test1!>.M1() where S : Test1!", baseM1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(baseM1.TypeParameters[0].IsNotNullable); } } [Fact] public void DynamicConstraint_05() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); var baseM1 = m1.OverriddenMethod; Assert.Equal("void Test1.M1(S x) where S : System.Object!, I1?", baseM1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(baseM1.TypeParameters[0].IsNotNullable); } } [Fact] public void NotNullConstraint_01() { var source1 = @" #nullable enable public class A { void Test(int? a, int? b) { M(a); M(a); if (b == null) return; b.Value.ToString(); M(b); } void M (T x) where T : notnull { ((object)x).ToString(); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (7,9): warning CS8714: The type 'int?' cannot be used as type parameter 'T' in the generic type or method 'A.M(T)'. Nullability of type argument 'int?' doesn't match 'notnull' constraint. // M(a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M").WithArguments("A.M(T)", "T", "int?").WithLocation(7, 9), // (8,9): warning CS8714: The type 'int?' cannot be used as type parameter 'T' in the generic type or method 'A.M(T)'. Nullability of type argument 'int?' doesn't match 'notnull' constraint. // M(a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M").WithArguments("A.M(T)", "T", "int?").WithLocation(8, 9), // (11,9): warning CS8714: The type 'int?' cannot be used as type parameter 'T' in the generic type or method 'A.M(T)'. Nullability of type argument 'int?' doesn't match 'notnull' constraint. // M(b); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M").WithArguments("A.M(T)", "T", "int?").WithLocation(11, 9) ); } [Fact] public void NotNullConstraint_02() { var source1 = @" #nullable enable public class A where T : notnull { public void M (S x) where S : T { ((object)x).ToString(); } } public class B : A { void Test(int? a, int? b) { M(a); M(a); if (b == null) return; b.Value.ToString(); M(b); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (15,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M(a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "System.ValueType", "S", "int?").WithLocation(15, 9), // (16,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M(a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "System.ValueType", "S", "int?").WithLocation(16, 9), // (19,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M(b); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "System.ValueType", "S", "int?").WithLocation(19, 9) ); } [Fact] public void NotNullConstraint_03() { var source1 = @" #nullable enable public class A { public void M (S x) where S : T { ((object)x).ToString(); } } public class B : A { void Test(int? a, int? b) { M(a); M(a); if (b == null) return; b.Value.ToString(); M(b); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (7,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((object)x).ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x").WithLocation(7, 10), // (7,10): warning CS8602: Dereference of a possibly null reference. // ((object)x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object)x").WithLocation(7, 10), // (15,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M(a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "System.ValueType", "S", "int?").WithLocation(15, 9), // (16,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M(a); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "System.ValueType", "S", "int?").WithLocation(16, 9), // (19,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M(b); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "System.ValueType", "S", "int?").WithLocation(19, 9) ); } [Fact] public void NotNullConstraint_04() { var source1 = @" #nullable enable public class A { public void M (S x) where S : T { ((object)x).ToString(); } } public class B : A { void Test(int? a, int? b) { M(a); M(a); if (b == null) return; b.Value.ToString(); M(b); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (7,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((object)x).ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x").WithLocation(7, 10), // (7,10): warning CS8602: Dereference of a possibly null reference. // ((object)x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object)x").WithLocation(7, 10) ); } [Fact] public void NotNullConstraint_05() { var source1 = @" #nullable enable public class A where T : notnull { public void M (S x) where S : T { ((object)x).ToString(); } } public class B : A { void Test(int? a, int? b) { M(a); M(a); if (b == null) return; b.Value.ToString(); M(b); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (11,14): warning CS8714: The type 'System.ValueType?' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'System.ValueType?' doesn't match 'notnull' constraint. // public class B : A Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "B").WithArguments("A", "T", "System.ValueType?").WithLocation(11, 14) ); } [Fact] public void NotNullConstraint_06() { var source1 = @" #nullable enable public class A where T : notnull { public void M(S? x, S y, S? z) where S : class, T { M(x); M(x); if (z == null) return; M(z); } public void M(S x) where S : T { ((object)x).ToString(); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (7,9): warning CS8631: The type 'S?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'S?' doesn't match constraint type 'T'. // M(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "T", "S", "S?").WithLocation(7, 9), // (8,9): warning CS8631: The type 'S?' cannot be used as type parameter 'S' in the generic type or method 'A.M(S)'. Nullability of type argument 'S?' doesn't match constraint type 'T'. // M(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M(S)", "T", "S", "S?").WithLocation(8, 9) ); } [Fact] [WorkItem(36005, "https://github.com/dotnet/roslyn/issues/36005")] public void NotNullConstraint_07() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : T { } public virtual void M2(T x) { } } public class Test2 : Test1 { public override void M1(S x) { object y = x; y.ToString(); } public override void M2(System.ValueType x) { } public void Test() { int? x = null; M1(x); // 1 M2(x); // 2 } } public class Test3 : Test1 { public override void M1(S x) { object y = x; y.ToString(); } public override void M2(object x) { } public void Test() { int? x = null; M1(x); // 3 M2(x); // 4 } } public class Test4 : Test1 { public override void M1(S x) { object y = x; // 5 y.ToString(); // 6 } public override void M2(int? x) { } public void Test() { int? x = null; M1(x); M2(x); } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (26,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'Test2.M1(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M1(x); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test2.M1(S)", "System.ValueType", "S", "int?").WithLocation(26, 9), // (27,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void Test2.M2(ValueType x)'. // M2(x); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void Test2.M2(ValueType x)").WithLocation(27, 12), // (46,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'Test3.M1(S)'. Nullability of type argument 'int?' doesn't match constraint type 'object'. // M1(x); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test3.M1(S)", "object", "S", "int?").WithLocation(46, 9), // (47,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void Test3.M2(object x)'. // M2(x); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void Test3.M2(object x)").WithLocation(47, 12), // (55,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = x; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(55, 20), // (56,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(56, 9) ); var source2 = @" #nullable enable public class Test22 : Test2 { public override void M1(S x) { object y = x; y.ToString(); } public new void Test() { int? x = null; M1(x); // 1 M2(x); // 2 } } public class Test33 : Test3 { public override void M1(S x) { object y = x; y.ToString(); } public new void Test() { int? x = null; M1(x); // 3 M2(x); // 4 } } public class Test44 : Test4 { public override void M1(S x) { object y = x; // 5 y.ToString(); // 6 } public new void Test() { int? x = null; M1(x); M2(x); } } "; var comp2 = CreateCompilation(new[] { source2 }, references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics( // (14,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'Test22.M1(S)'. Nullability of type argument 'int?' doesn't match constraint type 'System.ValueType'. // M1(x); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test22.M1(S)", "System.ValueType", "S", "int?").WithLocation(14, 9), // (15,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void Test2.M2(ValueType x)'. // M2(x); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void Test2.M2(ValueType x)").WithLocation(15, 12), // (29,9): warning CS8631: The type 'int?' cannot be used as type parameter 'S' in the generic type or method 'Test33.M1(S)'. Nullability of type argument 'int?' doesn't match constraint type 'object'. // M1(x); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test33.M1(S)", "object", "S", "int?").WithLocation(29, 9), // (30,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void Test3.M2(object x)'. // M2(x); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "void Test3.M2(object x)").WithLocation(30, 12), // (38,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = x; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(38, 20), // (39,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(39, 9) ); } [Fact] public void NotNullConstraint_08() { var source1 = @" #nullable enable public class A { void M (T x) where T : notnull? { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (5,31): error CS0246: The type or namespace name 'notnull' could not be found (are you missing a using directive or an assembly reference?) // void M (T x) where T : notnull? Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "notnull").WithArguments("notnull").WithLocation(5, 31), // (5,31): error CS0701: 'notnull?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // void M (T x) where T : notnull? Diagnostic(ErrorCode.ERR_BadBoundType, "notnull?").WithArguments("notnull?").WithLocation(5, 31) ); } [Fact] public void NotNullConstraint_09() { var source1 = @" #nullable enable public class A { void M() where T : notnull { } void Test() { M(); M(); M(); } } class notnull {} "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (12,9): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A.M()'. There is no implicit reference conversion from 'object' to 'notnull'. // M(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M").WithArguments("A.M()", "notnull", "T", "object").WithLocation(12, 9), // (13,9): warning CS8631: The type 'notnull?' cannot be used as type parameter 'T' in the generic type or method 'A.M()'. Nullability of type argument 'notnull?' doesn't match constraint type 'notnull'. // M(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M").WithArguments("A.M()", "notnull", "T", "notnull?").WithLocation(13, 9) ); } [Fact] public void NotNullConstraint_10() { var source1 = @" #nullable enable public class A { void M() where T : notnull? { } void Test() { M(); M(); M(); } } class notnull {} "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (12,9): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'A.M()'. There is no implicit reference conversion from 'object' to 'notnull'. // M(); Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M").WithArguments("A.M()", "notnull", "T", "object").WithLocation(12, 9) ); } [Fact] public void NotNullConstraint_11() { var source1 = @" #nullable enable public class A { void M() where notnull : notnull { } void Test() { M(); M(); M(); } } class notnull {} "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (5,12): error CS0454: Circular constraint dependency involving 'notnull' and 'notnull' // void M() where notnull : notnull Diagnostic(ErrorCode.ERR_CircularConstraint, "notnull").WithArguments("notnull", "notnull").WithLocation(5, 12) ); } [Fact] public void NotNullConstraint_12() { var source1 = @" #nullable enable public class A { void M() where notnull : notnull? { } void Test() { M(); M(); M(); } } class notnull {} "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (5,12): error CS0454: Circular constraint dependency involving 'notnull' and 'notnull' // void M() where notnull : notnull? Diagnostic(ErrorCode.ERR_CircularConstraint, "notnull").WithArguments("notnull", "notnull").WithLocation(5, 12), // (5,39): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void M() where notnull : notnull? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "notnull?").WithLocation(5, 39) ); } [Fact] public void NotNullConstraint_13() { var source1 = @" #nullable enable public class A { void M() where notnull : notnull { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (5,12): error CS0454: Circular constraint dependency involving 'notnull' and 'notnull' // void M() where notnull : notnull Diagnostic(ErrorCode.ERR_CircularConstraint, "notnull").WithArguments("notnull", "notnull").WithLocation(5, 12) ); } [Fact] public void NotNullConstraint_14() { var source1 = @" #nullable enable public class A { void M() where notnull : notnull? { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics( // (5,12): error CS0454: Circular constraint dependency involving 'notnull' and 'notnull' // void M() where notnull : notnull? Diagnostic(ErrorCode.ERR_CircularConstraint, "notnull").WithArguments("notnull", "notnull").WithLocation(5, 12), // (5,39): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void M() where notnull : notnull? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "notnull?").WithLocation(5, 39) ); } [Fact] public void ObjectConstraint_01() { var source = @" class B { public static void F1() where T1 : object { } public static void F2() where T2 : System.Object { } }"; foreach (var options in new[] { WithNonNullTypesTrue(), WithNonNullTypesFalse() }) { var comp1 = CreateCompilation(new[] { source }, options: options); comp1.VerifyDiagnostics( // (4,44): error CS0702: Constraint cannot be special class 'object' // public static void F1() where T1 : object Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object").WithArguments("object").WithLocation(4, 44), // (8,44): error CS0702: Constraint cannot be special class 'object' // public static void F2() where T2 : System.Object Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "System.Object").WithArguments("object").WithLocation(8, 44) ); } } [Fact] public void ObjectConstraint_02() { var source = @" class B { public static void F1() where T1 : object? { } public static void F2() where T2 : System.Object? { } }"; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (4,44): error CS0702: Constraint cannot be special class 'object' // public static void F1() where T1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(4, 44), // (8,44): error CS0702: Constraint cannot be special class 'object' // public static void F2() where T2 : System.Object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "System.Object?").WithArguments("object").WithLocation(8, 44) ); var comp2 = CreateCompilation(new[] { source }, options: WithNonNullTypesFalse()); comp2.VerifyDiagnostics( // (4,44): error CS0702: Constraint cannot be special class 'object' // public static void F1() where T1 : object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object?").WithArguments("object").WithLocation(4, 44), // (4,50): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static void F1() where T1 : object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 50), // (8,44): error CS0702: Constraint cannot be special class 'object' // public static void F2() where T2 : System.Object? Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "System.Object?").WithArguments("object").WithLocation(8, 44), // (8,57): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public static void F2() where T2 : System.Object? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 57) ); } [Fact] public void ObjectConstraint_03() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : T {} } public class Test2 : Test1 { } public class Test3 : Test1 { public override void M1(S x) { } } public class Test4 : Test1 { } public class Test5 : Test1 { public override void M1(S x) { } } #nullable disable public class Test6 : Test1 { } public class Test7 : Test1 { #nullable enable public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); var source2 = @" #nullable enable public class Test21 : Test2 { public void Test() { M1(new object()); // 1 } } public class Test22 : Test2 { public override void M1(S x) { x.ToString(); x = default; // 2 } public void Test() { M1(new object()); // 3 } } public class Test31 : Test3 { public void Test() { M1(new object()); // 4 } } public class Test32 : Test3 { public override void M1(S x) { x.ToString(); x = default; // 5 } public void Test() { M1(new object()); // 6 } } public class Test41 : Test4 { public void Test() { M1(new object()); } } public class Test42 : Test4 { public override void M1(S x) { x.ToString(); // 7 x = default; // 8 } public void Test() { M1(new object()); } } public class Test51 : Test5 { public void Test() { M1(new object()); } } public class Test52 : Test5 { public override void M1(S x) { x.ToString(); // 9 x = default; // 10 } public void Test() { M1(new object()); } } public class Test61 : Test6 { public void Test() { M1(new object()); } } public class Test62 : Test6 { public override void M1(S x) { x.ToString(); x = default; // 11 } public void Test() { M1(new object()); } } public class Test71 : Test7 { public void Test() { M1(new object()); } } public class Test72 : Test7 { public override void M1(S x) { x.ToString(); x = default; // 12 } public void Test() { M1(new object()); } } "; foreach (var reference in new[] { comp1.ToMetadataReference(), comp1.EmitToImageReference() }) { var comp2 = CreateCompilation(new[] { source2 }, references: new[] { reference }); comp2.VerifyDiagnostics( // (7,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test1.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. // M1(new object()); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test1.M1(S)", "object", "S", "object?").WithLocation(7, 9), // (16,13): warning CS8653: A default expression introduces a null value when 'S' is a non-nullable reference type. // x = default; // 2 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("S").WithLocation(16, 13), // (21,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test22.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. // M1(new object()); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test22.M1(S)", "object", "S", "object?").WithLocation(21, 9), // (29,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test3.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. // M1(new object()); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test3.M1(S)", "object", "S", "object?").WithLocation(29, 9), // (38,13): warning CS8653: A default expression introduces a null value when 'S' is a non-nullable reference type. // x = default; // 5 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("S").WithLocation(38, 13), // (43,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test32.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. // M1(new object()); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test32.M1(S)", "object", "S", "object?").WithLocation(43, 9), // (59,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(59, 9), // (60,13): warning CS8653: A default expression introduces a null value when 'S' is a non-nullable reference type. // x = default; // 8 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("S").WithLocation(60, 13), // (81,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(81, 9), // (82,13): warning CS8653: A default expression introduces a null value when 'S' is a non-nullable reference type. // x = default; // 10 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("S").WithLocation(82, 13), // (104,13): warning CS8653: A default expression introduces a null value when 'S' is a non-nullable reference type. // x = default; // 11 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("S").WithLocation(104, 13), // (126,13): warning CS8653: A default expression introduces a null value when 'S' is a non-nullable reference type. // x = default; // 12 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("S").WithLocation(126, 13) ); } } [Fact] public void ObjectConstraint_04() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : T {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x)", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_05() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : T {} } #nullable enable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_06() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : T {} } #nullable enable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x)", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.False(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_07() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : I1, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_08() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T {} } public interface I1 {} #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_09() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1, T {} } public interface I1 {} #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_10() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_11() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_12() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : I1, T {} } public interface I1 {} #nullable enable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_13() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : class, T {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : class", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_14() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : class?, T {} } #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : class?, System.Object", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_15() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : class, T {} } #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : class!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_16() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : class, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S! x) where S : class!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_17() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : class?, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S! x) where S : class?, System.Object!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_18() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : class, T {} } public interface I1 {} #nullable enable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S! x) where S : class, System.Object!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_19() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : notnull, T {} } #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : notnull", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_20() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : notnull, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : notnull", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_21() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : struct, T {} } #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : struct", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_22() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : struct, T {} } public interface I1 {} public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : struct", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_23() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : U, T {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Int32", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_24() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : U, T {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Int32", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_25() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : U, T {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object, System.Int32?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_26() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : U, T {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!, System.Int32?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_27() { string il = @" .class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: ret } // end of method EmbeddedAttribute::.ctor } // end of class Microsoft.CodeAnalysis.EmbeddedAttribute .class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) .field public initonly uint8[] NullableFlags .method public hidebysig specialname rtspecialname instance void .ctor(uint8 A_1) cil managed { // Code size 24 (0x18) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: ldarg.0 IL_0008: ldc.i4.1 IL_0009: newarr [mscorlib]System.Byte IL_000e: dup IL_000f: ldc.i4.0 IL_0010: ldarg.1 IL_0011: stelem.i1 IL_0012: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags IL_0017: ret } // end of method NullableAttribute::.ctor .method public hidebysig specialname rtspecialname instance void .ctor(uint8[] A_1) cil managed { // Code size 15 (0xf) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: ldarg.0 IL_0008: ldarg.1 IL_0009: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags IL_000e: ret } // end of method NullableAttribute::.ctor } // end of class System.Runtime.CompilerServices.NullableAttribute .class interface public abstract auto ansi I1 { } // end of class I1 .class public auto ansi beforefieldinit Test2 extends class [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void class [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method Test2::.ctor .method public hidebysig instance void M1<([mscorlib]System.Object) S>(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M1 .method public hidebysig instance void M2<(I1, [mscorlib]System.Object) S>(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M2 .method public hidebysig instance void M3(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M3 .method public hidebysig virtual instance void M4(!!S x) cil managed { .param type S .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M4 .method public hidebysig virtual instance void M5(!!S x) cil managed { .param type S .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M5 .method public hidebysig virtual instance void M6<([mscorlib]System.Object) S>(!!S x) cil managed { .param type S .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M6 .method public hidebysig instance void M7(!!S x) cil managed { .param type S .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .param [1] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M7 .method public hidebysig instance void M8(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M8 .method public hidebysig virtual instance void M9<([mscorlib]System.Int32, [mscorlib]System.Object) S>(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M9 .method public hidebysig virtual instance void M10<(valuetype [mscorlib]System.Nullable`1, [mscorlib]System.Object) S>(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M10 } // end of class Test2 "; var compilation = CreateCompilationWithIL(new[] { "" }, il, options: WithNonNullTypesTrue()); var m1 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x)", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); var m2 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M2"); Assert.Equal("void Test2.M2(S x) where S : I1", m2.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m2.TypeParameters[0].IsNotNullable); var m3 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M3"); Assert.Equal("void Test2.M3(S x) where S : class", m3.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m3.TypeParameters[0].IsNotNullable); var m4 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M4"); Assert.Equal("void Test2.M4(S x) where S : class?, System.Object", m4.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m4.TypeParameters[0].IsNotNullable); var m5 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M5"); Assert.Equal("void Test2.M5(S x) where S : class!", m5.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m5.TypeParameters[0].IsNotNullable); var m6 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M6"); Assert.Equal("void Test2.M6(S x) where S : notnull", m6.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m6.TypeParameters[0].IsNotNullable); var m7 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M7"); Assert.Equal("void Test2.M7(S x)", m7.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.False(m7.TypeParameters[0].IsNotNullable); var m8 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M8"); Assert.Equal("void Test2.M8(S x) where S : struct", m8.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m8.TypeParameters[0].IsNotNullable); var m9 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M9"); Assert.Equal("void Test2.M9(S x) where S : System.Int32", m9.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m9.TypeParameters[0].IsNotNullable); var m10 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M10"); Assert.Equal("void Test2.M10(S x) where S : System.Object, System.Int32?", m10.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m10.TypeParameters[0].IsNotNullable); } [Fact] public void ObjectConstraint_28() { string il = @" .class public auto ansi beforefieldinit Test2 extends class [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void class [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method Test2::.ctor .method public hidebysig instance void M1<([mscorlib]System.Object, !!S) S,U>(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M1 } // end of class Test2 "; var compilation = CreateCompilationWithIL(new[] { "" }, il, options: WithNonNullTypesTrue()); var m1 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } [Fact] public void ObjectConstraint_29() { string il = @" .class public auto ansi beforefieldinit Test2 extends class [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void class [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method Test2::.ctor .method public hidebysig instance void M1<([mscorlib]System.Object, !!U) S, (!!S) U>(!!S x) cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Test2::M1 } // end of class Test2 "; var compilation = CreateCompilationWithIL(new[] { "" }, il, options: WithNonNullTypesTrue()); var m1 = (MethodSymbol)compilation.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object, U", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } [Fact] public void ObjectConstraint_30() { var source1 = @" #nullable disable public class Test1 { #nullable enable public virtual void M1(S x) where S : class?, T {} } #nullable disable public class Test2 : Test1 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : class?, System.Object", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_31() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable disable object, #nullable enable object? > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_32() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< object?, #nullable disable object > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_33() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable disable object, #nullable enable object > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_34() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< object, #nullable disable object > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_35() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : T1, T2 {} } public class Test2 : Test1 { public override void M1(S x) { } } #nullable enable public class Test3 : Test2 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var t2m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : T", t2m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(t2m1.TypeParameters[0].IsNotNullable); var t3m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test3.M1"); Assert.Equal("void Test3.M1(S x) where S : System.Object, Test3?", t3m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(t3m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_36() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : T1, T2 {} } public class Test2 : Test1 { public override void M1(S x) { } } "; var source2 = @" #nullable enable public class Test3 : Test2 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); var comp2 = CreateCompilation(new[] { source2 }, references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); CompileAndVerify(comp2, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var t3m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test3.M1"); Assert.Equal("void Test3.M1(S x) where S : System.Object, Test3?", t3m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(t3m1.TypeParameters[0].IsNotNullable); } } [Fact] public void ObjectConstraint_37() { var source1 = @" #nullable disable public class Test1 { public virtual void M1(S x) where S : T1, T2 {} } public class Test2 : Test1 where T : struct { public override void M1(S x) { } } #nullable enable public class Test3 : Test2 { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var t2m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : T", t2m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(t2m1.TypeParameters[0].IsNotNullable); var t3m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test3.M1"); Assert.Equal("void Test3.M1(S x) where S : System.Int32", t3m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(t3m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_01() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable disable string, #nullable enable string? > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1?, System.String", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_02() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< string?, #nullable disable string > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1?, System.String", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_03() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable disable string, #nullable enable string > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S! x) where S : I1?, System.String!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_04() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< string, #nullable disable string > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1?, System.String!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_05() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable enable string?, string? > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1?, System.String?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.False(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_06() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable enable string, string > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S! x) where S : I1?, System.String!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.True(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void DuplicateConstraintsIgnoringTopLevelNullability_07() { var source1 = @" #nullable enable public class Test1 { public virtual void M1(S x) where S : I1?, T1, T2 {} } public interface I1 {} public class Test2 : Test1< #nullable disable string, string > { public override void M1(S x) { } } "; var comp1 = CreateCompilation(new[] { source1 }); comp1.VerifyDiagnostics(); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("Test2.M1"); Assert.Equal("void Test2.M1(S x) where S : I1?, System.String", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); Assert.Null(m1.TypeParameters[0].IsNotNullable); } } [Fact] public void UnconstrainedTypeParameter_Local() { var source = @" #pragma warning disable CS0168 class B { public static void F1() { T1? x; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T1? x; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T1?").WithLocation(7, 9) ); } [Fact] public void ConstraintsChecks_01() { var source = @" #pragma warning disable CS0168 public interface IA where TA : ID { } public interface IB : IA> // 1 {} public interface IC : IA?> // 2 {} public interface IE : IA> {} public interface ID {} class B { public void Test1() { IA> x1; // 3 IA?> y1; // 4 IA> z1; } public void M1(TM1 x) where TM1: ID {} public void Test2(ID a2, ID b2, ID? c2) { M1(a2); // 5 M1(b2); M1(c2); // 6 M1>(a2); // 7 M1>(b2); // 8 M1?>(b2); // 9 M1>(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8631: The type 'ID' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'ID' doesn't match constraint type 'ID'. // public interface IB : IA> // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "IB").WithArguments("IA", "ID", "TA", "ID").WithLocation(8, 18), // (11,18): warning CS8631: The type 'ID?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'ID?' doesn't match constraint type 'ID'. // public interface IC : IA?> // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "IC").WithArguments("IA", "ID", "TA", "ID?").WithLocation(11, 18), // (24,12): warning CS8631: The type 'ID' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'ID' doesn't match constraint type 'ID'. // IA> x1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "ID").WithArguments("IA", "ID", "TA", "ID").WithLocation(24, 12), // (25,12): warning CS8631: The type 'ID?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'ID?' doesn't match constraint type 'ID'. // IA?> y1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "ID?").WithArguments("IA", "ID", "TA", "ID?").WithLocation(25, 12), // (34,9): warning CS8631: The type 'ID' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'ID' doesn't match constraint type 'ID'. // M1(a2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "ID").WithLocation(34, 9), // (36,9): warning CS8631: The type 'ID?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'ID?' doesn't match constraint type 'ID'. // M1(c2); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "ID?").WithLocation(36, 9), // (37,9): warning CS8631: The type 'ID' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'ID' doesn't match constraint type 'ID'. // M1>(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1>").WithArguments("B.M1(TM1)", "ID", "TM1", "ID").WithLocation(37, 9), // (38,9): warning CS8631: The type 'ID' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'ID' doesn't match constraint type 'ID'. // M1>(b2); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1>").WithArguments("B.M1(TM1)", "ID", "TM1", "ID").WithLocation(38, 9), // (38,25): warning CS8620: Nullability of reference types in argument of type 'ID' doesn't match target type 'ID' for parameter 'x' in 'void B.M1>(ID x)'. // M1>(b2); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b2").WithArguments("ID", "ID", "x", "void B.M1>(ID x)").WithLocation(38, 25), // (39,9): warning CS8631: The type 'ID?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'ID?' doesn't match constraint type 'ID'. // M1?>(b2); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1?>").WithArguments("B.M1(TM1)", "ID", "TM1", "ID?").WithLocation(39, 9) ); } [Fact] public void ConstraintsChecks_02() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class { } public interface IB : IA // 1 {} public interface IC : IA {} class B { public void Test1() { IA x1; // 2 IA z1; } public void M1(TM1 x) where TM1: class {} public void Test2(string? a2, string b2) { M1(a2); // 3 M1(b2); M1(a2); // 4 M1(b2); // 5 M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8634: The type 'string?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'string?' doesn't match 'class' constraint. // public interface IB : IA // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "IB").WithArguments("IA", "TA", "string?").WithLocation(8, 18), // (18,12): warning CS8634: The type 'string?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'string?' doesn't match 'class' constraint. // IA x1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("IA", "TA", "string?").WithLocation(18, 12), // (27,9): warning CS8634: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(27, 9), // (29,9): warning CS8634: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // M1(a2); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(29, 9), // (30,9): warning CS8634: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'class' constraint. // M1(b2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(30, 9) ); } [Fact] public void ConstraintsChecks_03() { var source = @" #pragma warning disable CS0168 public interface IA where TA : ID? { } public interface IC : IA?> {} public interface IE : IA> {} public interface ID {} class B { public void Test1() { IA?> y1; IA> z1; } public void M1(TM1 x) where TM1: ID? {} public void Test2(ID b2, ID? c2) { M1(b2); M1(c2); M1?>(c2); M1>(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( ); } [Fact] public void ConstraintsChecks_04() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class? { } public interface IB : IA {} public interface IC : IA {} class B { public void Test1() { IA x1; IA z1; } public void M1(TM1 x) where TM1: class? {} public void Test2(string? a2, string b2) { M1(a2); M1(b2); M1(a2); M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( ); } [Fact] public void ConstraintsChecks_05() { var source = @" #pragma warning disable CS0168 public interface IA where TA : ID { } public interface IB : IA where TIB : ID // 1 {} public interface IC : IA where TIC : ID? // 2 {} public interface IE : IA where TIE : ID {} public interface ID {} class B where TB1 : ID where TB2 : ID? where TB3 : ID { public void Test1() { IA x1; // 3 IA y1; // 4 IA z1; } public void M1(TM1 x) where TM1: ID {} public void Test2(TB1 a2, TB3 b2, TB2 c2) { M1(a2); // 5 M1(b2); M1(c2); // 6 M1(a2); // 7 M1(c2); // 8 M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8631: The type 'TIB' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIB' doesn't match constraint type 'ID'. // public interface IB : IA where TIB : ID // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "IB").WithArguments("IA", "ID", "TA", "TIB").WithLocation(8, 18), // (11,18): warning CS8631: The type 'TIC' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIC' doesn't match constraint type 'ID'. // public interface IC : IA where TIC : ID? // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "IC").WithArguments("IA", "ID", "TA", "TIC").WithLocation(11, 18), // (24,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // IA x1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "ID", "TA", "TB1").WithLocation(24, 12), // (25,12): warning CS8631: The type 'TB2' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // IA y1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB2").WithArguments("IA", "ID", "TA", "TB2").WithLocation(25, 12), // (34,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(34, 9), // (36,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(36, 9), // (37,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(37, 9), // (38,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(38, 9) ); } [Fact] public void ConstraintsChecks_06() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class { } public interface IB : IA where TIB : C? // 1 {} public interface IC : IA where TIC : C {} public class C {} class B where TB1 : C? where TB2 : C { public void Test1() { IA x1; // 2 IA z1; } public void M1(TM1 x) where TM1: class {} public void Test2(TB1 a2, TB2 b2) { M1(a2); // 3 M1(b2); M1(a2); // 4 M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8634: The type 'TIB' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIB' doesn't match 'class' constraint. // public interface IB : IA where TIB : C? // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "IB").WithArguments("IA", "TA", "TIB").WithLocation(8, 18), // (21,12): warning CS8634: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // IA x1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(21, 12), // (30,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(30, 9), // (32,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(32, 9) ); } [Fact] public void ConstraintsChecks_07() { var source = @" #pragma warning disable CS0168 public interface IA where TA : ID? { } public interface IC : IA where TIC : ID? {} public interface IE : IA where TIE : ID {} public interface ID {} class B where TB2 : ID? where TB3 : ID { public void Test1() { IA y1; IA z1; } public void M1(TM1 x) where TM1: ID? {} public void Test2(TB3 b2, TB2 c2) { M1(b2); M1(c2); M1(c2); M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics(); } [Fact] public void ConstraintsChecks_08() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class? { } public interface IB : IA where TIB : C? {} public interface IC : IA where TIC : C {} public class C {} class B where TB1 : C? where TB2 : C { public void Test1() { IA x1; IA z1; } public void M1(TM1 x) where TM1: class? {} public void Test2(TB1 a2, TB2 b2) { M1(a2); M1(b2); M1(a2); M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics(); } [Fact] public void ConstraintsChecks_09() { var source = @" #pragma warning disable CS0168 #nullable disable public interface IA where TA : ID { } #nullable enable public interface IC : IA?> {} public interface IE : IA> {} public interface ID {} class B { public void Test1() { IA?> y1; IA> z1; } #nullable disable public void M1(TM1 x) where TM1: ID {} #nullable enable public void Test2(ID b2, ID? c2) { M1(b2); M1(c2); M1?>(c2); M1>(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( ); } [Fact] public void ConstraintsChecks_10() { var source = @" #pragma warning disable CS0168 #nullable disable public interface IA where TA : class { } #nullable enable public interface IB : IA {} public interface IC : IA {} class B { public void Test1() { IA x1; IA z1; } #nullable disable public void M1(TM1 x) where TM1: class {} #nullable enable public void Test2(string? a2, string b2) { M1(a2); M1(b2); M1(a2); M1(b2); M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); CompileAndVerify(comp1, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); void symbolValidator(ModuleSymbol m) { var m1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.M1"); Assert.Equal("void B.M1(TM1 x) where TM1 : class", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); TypeParameterSymbol tm1 = m1.TypeParameters[0]; Assert.Null(tm1.ReferenceTypeConstraintIsNullable); Assert.Empty(tm1.GetAttributes()); } } [Fact] public void ConstraintsChecks_11() { var source = @" #pragma warning disable CS0168 public interface IA where TA : ID { } #nullable disable public interface IB : IA where TIB : ID // 1 {} #nullable disable public interface IC : IA where TIC : ID? // 2 {} #nullable disable public interface IE : IA where TIE : ID // 3 {} #nullable enable public interface ID {} #nullable disable class B where TB1 : ID where TB2 : ID? where TB3 : ID { #nullable enable public void Test1() { IA x1; // 4 IA y1; // 5 IA z1; // 6 } #nullable enable public void M1(TM1 x) where TM1: ID {} #nullable enable public void Test2(TB1 a2, TB3 b2, TB2 c2) { M1(a2); // 7 M1(b2); // 8 M1(c2); // 9 M1(a2); // 10 M1(c2); // 11 M1(b2); // 12 } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29678: Constraint violations are not reported for type references outside of method bodies. comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (24,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // IA x1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "ID", "TA", "TB1").WithLocation(24, 12), // (25,12): warning CS8631: The type 'TB2' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // IA y1; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB2").WithArguments("IA", "ID", "TA", "TB2").WithLocation(25, 12), // (34,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(34, 9), // (36,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(36, 9), // (37,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(37, 9), // (38,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(38, 9) ); } [Fact] public void ConstraintsChecks_12() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class { } #nullable disable public interface IB : IA where TIB : C? // 1 {} #nullable disable public interface IC : IA where TIC : C // 2 {} #nullable enable public class C {} #nullable disable class B where TB1 : C? where TB2 : C { #nullable enable public void Test1() { IA x1; // 3 IA z1; // 4 } #nullable enable public void M1(TM1 x) where TM1: class {} #nullable enable public void Test2(TB1 a2, TB2 b2) { M1(a2); // 5 M1(b2); // 6 M1(a2); // 7 M1(b2); // 8 } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29678: Constraint violations are not reported for type references outside of method bodies. comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (21,12): warning CS8634: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // IA x1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(21, 12), // (30,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(30, 9), // (32,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(32, 9) ); } [Fact] public void ConstraintsChecks_13() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class { } public interface IB : IA where TIB : class? // 1 {} public interface IC : IA where TIC : class {} class B where TB1 : class? where TB2 : class { public void Test1() { IA x1; // 2 IA z1; } public void M1(TM1 x) where TM1: class {} public void Test2(TB1 a2, TB2 b2) { M1(a2); // 3 M1(b2); M1(a2); // 4 M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8634: The type 'TIB' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIB' doesn't match 'class' constraint. // public interface IB : IA where TIB : class? // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "IB").WithArguments("IA", "TA", "TIB").WithLocation(8, 18), // (18,12): warning CS8634: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // IA x1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(18, 12), // (27,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(27, 9), // (29,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(29, 9) ); } [Fact] public void ConstraintsChecks_14() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class? { } public interface IB : IA where TIB : class? {} public interface IC : IA where TIC : class {} class B where TB1 : class? where TB2 : class { public void Test1() { IA x1; IA z1; } public void M1(TM1 x) where TM1: class? {} public void Test2(TB1 a2, TB2 b2) { M1(a2); M1(b2); M1(a2); M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics(); } [Fact] public void ConstraintsChecks_15() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class { } #nullable disable public interface IB : IA where TIB : class? // 1 {} #nullable disable public interface IC : IA where TIC : class // 2 {} #nullable disable class B where TB1 : class? where TB2 : class { #nullable enable public void Test1() { IA x1; // 3 IA z1; // 4 } #nullable enable public void M1(TM1 x) where TM1: class {} #nullable enable public void Test2(TB1 a2, TB2 b2) { M1(a2); // 5 M1(b2); // 6 M1(a2); // 7 M1(b2); // 8 } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29678: Constraint violations are not reported for type references outside of method bodies. comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (18,12): warning CS8634: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // IA x1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(18, 12), // (27,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(27, 9), // (29,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(29, 9) ); } [Fact] public void ConstraintsChecks_16() { var source = @" #pragma warning disable CS0168 public interface IA where TA : IE?, ID, IF? { } public interface IB : IA where TIB : IE?, ID, IF? // 1 {} public interface IC : IA where TIC : IE?, ID?, IF? // 2 {} public interface IE : IA where TIE : IE?, ID, IF? {} public interface ID {} class B where TB1 : IE?, ID, IF? where TB2 : IE?, ID?, IF? where TB3 : IE?, ID, IF? where TB4 : IE, ID?, IF? { public void Test1() { IA x1; // 3 IA y1; // 4 IA z1; IA u1; } public void M1(TM1 x) where TM1: IE?, ID, IF? {} public void Test2(TB1 a2, TB3 b2, TB2 c2, TB4 d2) { M1(a2); // 5 M1(b2); M1(c2); // 6 M1(d2); M1(a2); // 7 M1(c2); // 8 M1(b2); M1(d2); } } public interface IE {} public interface IF {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8631: The type 'TIB' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIB' doesn't match constraint type 'ID'. // public interface IB : IA where TIB : IE?, ID, IF? // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "IB").WithArguments("IA", "ID", "TA", "TIB").WithLocation(8, 18), // (11,18): warning CS8631: The type 'TIC' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIC' doesn't match constraint type 'ID'. // public interface IC : IA where TIC : IE?, ID?, IF? // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "IC").WithArguments("IA", "ID", "TA", "TIC").WithLocation(11, 18), // (28,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // IA x1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "ID", "TA", "TB1").WithLocation(28, 12), // (29,12): warning CS8631: The type 'TB2' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // IA y1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB2").WithArguments("IA", "ID", "TA", "TB2").WithLocation(29, 12), // (39,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(39, 9), // (41,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(41, 9), // (43,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(43, 9), // (44,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(44, 9) ); } [Fact] public void ConstraintsChecks_17() { var source = @" #pragma warning disable CS0168 #nullable disable public interface IA where TA : IE?, ID, IF? { } #nullable enable public interface IB : IA where TIB : IE?, ID, IF? {} public interface IC : IA where TIC : IE?, ID?, IF? {} public interface IE : IA where TIE : IE?, ID, IF? {} public interface ID {} class B where TB1 : IE?, ID, IF? where TB2 : IE?, ID?, IF? where TB3 : IE?, ID, IF? where TB4 : IE, ID?, IF? { public void Test1() { IA x1; IA y1; IA z1; IA u1; } #nullable disable public void M1(TM1 x) where TM1: IE?, ID, IF? {} #nullable enable public void Test2(TB1 a2, TB3 b2, TB2 c2, TB4 d2) { M1(a2); M1(b2); M1(c2); M1(d2); M1(a2); M1(c2); M1(b2); M1(d2); } } public interface IE {} public interface IF {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify(); } [Fact] public void ConstraintsChecks_18() { var source = @" #pragma warning disable CS0168 public interface IA where TA : IE?, ID, IF? { } #nullable disable public interface IB : IA where TIB : IE?, ID, IF? // 1 {} #nullable disable public interface IC : IA where TIC : IE?, ID?, IF? // 2 {} #nullable disable public interface IE : IA where TIE : IE?, ID, IF? // 3 {} #nullable enable public interface ID {} #nullable disable class B where TB1 : IE?, ID, IF? where TB2 : IE?, ID?, IF? where TB3 : IE?, ID, IF? where TB4 : IE, ID?, IF? { #nullable enable public void Test1() { IA x1; // 4 IA y1; // 5 IA z1; // 6 IA u1; // 7 } #nullable enable public void M1(TM1 x) where TM1: IE?, ID, IF? {} #nullable enable public void Test2(TB1 a2, TB3 b2, TB2 c2, TB4 d2) { M1(a2); // 8 M1(b2); // 9 M1(c2); // 10 M1(d2); // 11 M1(a2); // 12 M1(c2); // 13 M1(b2); // 14 M1(d2); // 15 } } public interface IE {} public interface IF {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29678: Constraint violations are not reported for type references outside of method bodies. comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (33,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // IA x1; // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "ID", "TA", "TB1").WithLocation(33, 12), // (34,12): warning CS8631: The type 'TB2' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // IA y1; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB2").WithArguments("IA", "ID", "TA", "TB2").WithLocation(34, 12), // (46,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(46, 9), // (48,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(48, 9), // (50,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'ID'. // M1(a2); // 12 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB1").WithLocation(50, 9), // (51,9): warning CS8631: The type 'TB2' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB2' doesn't match constraint type 'ID'. // M1(c2); // 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "ID", "TM1", "TB2").WithLocation(51, 9) ); } [Fact] public void ConstraintsChecks_19() { var source = @" #pragma warning disable CS0168 public interface IA where TA : class, IB, IC { } class B where TB1 : class?, IB?, IC? { public void Test1() { IA x1; // 1 } public void M1(TM1 x) where TM1: class, IB, IC {} public void Test2(TB1 a2) { M1(a2); // 2 M1(a2); // 3 } } public interface IB {} public interface IC {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (12,12): warning CS8634: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // IA x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(12, 12), // (12,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'IB'. // IA x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "IB", "TA", "TB1").WithLocation(12, 12), // (12,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'IC'. // IA x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "IC", "TA", "TB1").WithLocation(12, 12), // (20,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(20, 9), // (20,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IB'. // M1(a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IB", "TM1", "TB1").WithLocation(20, 9), // (20,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IC'. // M1(a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IC", "TM1", "TB1").WithLocation(20, 9), // (21,9): warning CS8634: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'class' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(21, 9), // (21,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IB'. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IB", "TM1", "TB1").WithLocation(21, 9), // (21,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IC'. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IC", "TM1", "TB1").WithLocation(21, 9) ); } [Fact] public void ConstraintsChecks_20() { var source = @" class B where TB1 : class, IB? { public void M1(TM1 x, TM2 y) where TM2 : TM1 {} public void Test2(TB1? a2, TB1 b2) { M1(b2, a2); // 1 M1(b2, a2); // 2 } } public interface IB {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (9,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(9, 9), // (10,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(10, 9) ); } [Fact] public void ConstraintsChecks_21() { var source = @" class B where TB1 : class?, IB { public void M1(TM1 x, TM2 y) where TM2 : TM1 {} public void Test2(TB1? a2, TB1 b2) { M1(b2, a2); // 1 M1(b2, a2); // 2 } } public interface IB {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (9,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(9, 9), // (10,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(10, 9) ); } [Fact] public void ConstraintsChecks_22() { var source = @" class B where TB1 : class, IB? { #nullable disable public void M1(TM1 x, TM2 y) where TM2 : TM1 {} #nullable enable public void Test2(TB1? a2, TB1 b2) { M1(b2, a2); // 1 M1(b2, a2); // 2 } } public interface IB {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (9,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(9, 9), // (10,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(10, 9) ); } [Fact] public void ConstraintsChecks_23() { var source = @" class B where TB1 : A?, IB, IC? { public void M1(TM1 x, TM2 y) where TM2 : TM1 {} public void Test2(TB1? a2, TB1 b2) { M1(b2, a2); // 1 M1(b2, a2); // 2 } } public class A {} public interface IB {} public interface IC {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (9,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(9, 9), // (10,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(10, 9) ); } [Fact] public void ConstraintsChecks_24() { var source = @" class B where TB1 : A?, IB, IC? { #nullable disable public void M1(TM1 x, TM2 y) where TM2 : TM1 {} #nullable enable public void Test2(TB1? a2, TB1 b2) { M1(b2, a2); // 1 M1(b2, a2); // 2 } } public class A {} public interface IB {} public interface IC {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (9,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(9, 9), // (10,9): warning CS8631: The type 'TB1?' cannot be used as type parameter 'TM2' in the generic type or method 'B.M1(TM1, TM2)'. Nullability of type argument 'TB1?' doesn't match constraint type 'TB1'. // M1(b2, a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1, TM2)", "TB1", "TM2", "TB1?").WithLocation(10, 9) ); } [Fact] public void ConstraintsChecks_25() { var source = @" #pragma warning disable CS0168 public interface IA where TA : notnull { } public interface IB : IA // 1 {} public interface IC : IA {} class B { public void Test1() { IA x1; // 2 IA z1; } public void M1(TM1 x) where TM1: notnull {} public void Test2(string? a2, string b2) { M1(a2); // 3 M1(b2); M1(a2); // 4 M1(b2); // 5 M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8714: The type 'string?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // public interface IB : IA // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "IB").WithArguments("IA", "TA", "string?").WithLocation(8, 18), // (18,12): warning CS8714: The type 'string?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // IA x1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("IA", "TA", "string?").WithLocation(18, 12), // (27,9): warning CS8714: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(27, 9), // (29,9): warning CS8714: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // M1(a2); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(29, 9), // (30,9): warning CS8714: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // M1(b2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(30, 9) ); } [Fact] public void ConstraintsChecks_26() { var source = @" #pragma warning disable CS0168 #nullable disable public interface IA where TA : notnull { } #nullable enable public interface IB : IA {} public interface IC : IA {} class B { public void Test1() { IA x1; IA z1; } #nullable disable public void M1(TM1 x) where TM1: notnull {} #nullable enable public void Test2(string? a2, string b2) { M1(a2); M1(b2); M1(a2); M1(b2); M1(b2); } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (8,18): warning CS8714: The type 'string?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // public interface IB : IA Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "IB").WithArguments("IA", "TA", "string?").WithLocation(8, 18), // (18,12): warning CS8714: The type 'string?' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // IA x1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "string?").WithArguments("IA", "TA", "string?").WithLocation(18, 12), // (27,9): warning CS8714: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // M1(a2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(27, 9), // (29,9): warning CS8714: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // M1(a2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(29, 9), // (30,9): warning CS8714: The type 'string?' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'string?' doesn't match 'notnull' constraint. // M1(b2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "string?").WithLocation(30, 9) ); } [Fact] [WorkItem(34843, "https://github.com/dotnet/roslyn/issues/34843")] public void ConstraintsChecks_27() { var source = @" #pragma warning disable CS0168 public interface IA where TA : notnull { } #nullable disable public interface IB : IA where TIB : C? // 1 {} #nullable disable public interface IC : IA where TIC : C // 2 {} public class C {} #nullable disable class B where TB1 : C? where TB2 : C { #nullable enable public void Test1() { IA x1; // 3 IA z1; // 4 } #nullable enable public void M1(TM1 x) where TM1: notnull {} #nullable enable public void Test2(TB1 a2, TB2 b2) { M1(a2); // 5 M1(b2); // 6 M1(a2); // 7 M1(b2); // 8 } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29678: Constraint violations are not reported for type references outside of method bodies. comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify( // (21,12): warning CS8714: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // IA x1; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(21, 12), // (30,9): warning CS8714: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // M1(a2); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(30, 9), // (32,9): warning CS8714: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // M1(a2); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(32, 9) ); } [Fact] public void ConstraintsChecks_28() { var source0 = @" public interface IA where TA : notnull { } public class A { public void M1(TM1 x) where TM1: notnull {} } "; var source1 = @" #pragma warning disable CS0168 public interface IB : IA // 1 {} public interface IC : IA where TIC : notnull {} class B : A where TB2 : notnull { public void Test1() { IA x1; // 2 IA z1; } public void Test2(TB1 a2, TB2 b2) { M1(a2); // 3 M1(b2); M1(a2); // 4 M1(b2); } } "; var comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); foreach (var reference in new[] { comp0.ToMetadataReference(), comp0.EmitToImageReference() }) { var comp1 = CreateCompilation(new[] { source1 }, options: WithNonNullTypesTrue(), references: new[] { reference }); comp1.VerifyDiagnostics( // (4,18): warning CS8714: The type 'TIB' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TIB' doesn't match 'notnull' constraint. // public interface IB : IA // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "IB").WithArguments("IA", "TA", "TIB").WithLocation(4, 18), // (14,12): warning CS8714: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // IA x1; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(14, 12), // (20,9): warning CS8714: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'A.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("A.M1(TM1)", "TM1", "TB1").WithLocation(20, 9), // (22,9): warning CS8714: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'A.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // M1(a2); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("A.M1(TM1)", "TM1", "TB1").WithLocation(22, 9) ); } } [Fact] public void ConstraintsChecks_29() { var source = @" #pragma warning disable CS0168 public interface IA where TA : notnull { } #nullable disable public interface IB : IA // 1 {} #nullable disable public interface IC : IA where TIC : notnull // 2 {} #nullable disable class B where TB2 : notnull { #nullable enable public void Test1() { IA x1; // 3 IA z1; // 4 } #nullable enable public void M1(TM1 x) where TM1: notnull {} #nullable enable public void Test2(TB1 a2, TB2 b2) { M1(a2); // 5 M1(b2); // 6 M1(a2); // 7 M1(b2); // 8 } } "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29678: Constraint violations are not reported for type references outside of method bodies. comp1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify(); } [Fact] public void ConstraintsChecks_30() { var source = @" #pragma warning disable CS0168 public interface IA where TA : notnull, IB, IC { } class B where TB1 : IB?, IC? { public void Test1() { IA x1; // 1 } public void M1(TM1 x) where TM1: notnull, IB, IC {} public void Test2(TB1 a2) { M1(a2); // 2 M1(a2); // 3 } } public interface IB {} public interface IC {} "; var comp1 = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp1.VerifyDiagnostics( // (12,12): warning CS8714: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // IA x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "TB1").WithArguments("IA", "TA", "TB1").WithLocation(12, 12), // (12,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'IB'. // IA x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "IB", "TA", "TB1").WithLocation(12, 12), // (12,12): warning CS8631: The type 'TB1' cannot be used as type parameter 'TA' in the generic type or method 'IA'. Nullability of type argument 'TB1' doesn't match constraint type 'IC'. // IA x1; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "TB1").WithArguments("IA", "IC", "TA", "TB1").WithLocation(12, 12), // (20,9): warning CS8714: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // M1(a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(20, 9), // (20,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IB'. // M1(a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IB", "TM1", "TB1").WithLocation(20, 9), // (20,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IC'. // M1(a2); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IC", "TM1", "TB1").WithLocation(20, 9), // (21,9): warning CS8714: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match 'notnull' constraint. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("B.M1(TM1)", "TM1", "TB1").WithLocation(21, 9), // (21,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IB'. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IB", "TM1", "TB1").WithLocation(21, 9), // (21,9): warning CS8631: The type 'TB1' cannot be used as type parameter 'TM1' in the generic type or method 'B.M1(TM1)'. Nullability of type argument 'TB1' doesn't match constraint type 'IC'. // M1(a2); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("B.M1(TM1)", "IC", "TM1", "TB1").WithLocation(21, 9) ); } [Fact] [WorkItem(34892, "https://github.com/dotnet/roslyn/issues/34892")] public void ConstraintsChecks_31() { var source = @" #nullable enable public class AA { public void M3(T3 z) where T3 : class { } public void M4(T4 z) where T4 : AA { } #nullable disable public void F1(T1 x) where T1 : class { #nullable enable M3(x); } #nullable disable public void F2(T2 x) where T2 : AA { #nullable enable M4(x); } } "; var comp1 = CreateCompilation(source); comp1.VerifyDiagnostics(); } [Fact] [WorkItem(34844, "https://github.com/dotnet/roslyn/issues/34844")] public void ConstraintsChecks_32() { var source = @" #pragma warning disable CS0649 #nullable disable class A where T2 : class where T3 : notnull { T1 F1; T2 F2; T3 F3; B F4; #nullable enable void M3() { C.Test(); C.Test(); C.Test(); } void M4() { D.Test(F1); D.Test(F2); D.Test(F3); D.Test(F4); } } class B {} class C { public static void Test() where T : notnull {} } class D { public static void Test(T x) where T : notnull {} } "; var comp1 = CreateCompilation(source); comp1.VerifyDiagnostics(); } // https://github.com/dotnet/roslyn/issues/29981: Should report CS8600 for `T1 t = (T1)NullableObject();` // and `T3 t = (T3)NullableObject();`. (See VisitConversion which skips reporting because the // `object?` has an Unboxing conversion. Should report warning on unconverted operand // when Unboxing.) [Fact] [WorkItem(29981, "https://github.com/dotnet/roslyn/issues/29981")] public void UnconstrainedTypeParameter_MayBeNonNullable() { var source = @"class C1 { static object? NullableObject() => null; static T1 F1() => default; // warn: return type T1 may be non-null static T1 F2() => default(T1); // warn: return type T1 may be non-null static void F4() { T1 t1 = (T1)NullableObject(); // warn: T1 may be non-null } } class C2 where T2 : class { static object? NullableObject() => null; static T2 F1() => default; // warn: return type T2 may be non-null static T2 F2() => default(T2); // warn: return type T2 may be non-null static void F4() { T2 t2 = (T2)NullableObject(); // warn: T2 may be non-null } } class C3 where T3 : new() { static object? NullableObject() => null; static T3 F1() => default; // warn: return type T3 may be non-null static T3 F2() => default(T3); // warn: return type T3 may be non-null static T3 F3() => new T3(); static void F4() { T3 t = (T3)NullableObject(); // warn: T3 may be non-null } } class C4 where T4 : I { static object? NullableObject() => null; static T4 F1() => default; // warn: return type T4 may be non-null static T4 F2() => default(T4); // warn: return type T4 may be non-null static void F4() { T4 t4 = (T4)NullableObject(); // warn: T4 may be non-null } } class C5 where T5 : A { static object? NullableObject() => null; static T5 F1() => default; // warn: return type T5 may be non-null static T5 F2() => default(T5); // warn: return type T5 may be non-null static void F4() { T5 t5 = (T5)NullableObject(); // warn: T5 may be non-null } } interface I { } class A { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29981: missing warnings comp.VerifyDiagnostics( // (4,23): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // static T1 F1() => default; // warn: return type T1 may be non-null Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(4, 23), // (14,23): warning CS8603: Possible null reference return. // static T2 F1() => default; // warn: return type T2 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(14, 23), // (45,23): warning CS8603: Possible null reference return. // static T5 F1() => default; // warn: return type T5 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default").WithLocation(45, 23), // (35,23): warning CS8653: A default expression introduces a null value when 'T4' is a non-nullable reference type. // static T4 F1() => default; // warn: return type T4 may be non-null Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T4").WithLocation(35, 23), // (24,23): warning CS8653: A default expression introduces a null value when 'T3' is a non-nullable reference type. // static T3 F1() => default; // warn: return type T3 may be non-null Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T3").WithLocation(24, 23), // (5,23): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // static T1 F2() => default(T1); // warn: return type T1 may be non-null Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T1)").WithArguments("T1").WithLocation(5, 23), // (15,23): warning CS8603: Possible null reference return. // static T2 F2() => default(T2); // warn: return type T2 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T2)").WithLocation(15, 23), // (46,23): warning CS8603: Possible null reference return. // static T5 F2() => default(T5); // warn: return type T5 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceReturn, "default(T5)").WithLocation(46, 23), // (36,23): warning CS8653: A default expression introduces a null value when 'T4' is a non-nullable reference type. // static T4 F2() => default(T4); // warn: return type T4 may be non-null Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T4)").WithArguments("T4").WithLocation(36, 23), // (25,23): warning CS8653: A default expression introduces a null value when 'T3' is a non-nullable reference type. // static T3 F2() => default(T3); // warn: return type T3 may be non-null Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T3)").WithArguments("T3").WithLocation(25, 23), // (8,17): warning CS8601: Possible null reference assignment. // T1 t1 = (T1)NullableObject(); // warn: T1 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T1)NullableObject()").WithLocation(8, 17), // (18,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // T2 t2 = (T2)NullableObject(); // warn: T2 may be non-null Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T2)NullableObject()").WithLocation(18, 17), // (49,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // T5 t5 = (T5)NullableObject(); // warn: T5 may be non-null Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T5)NullableObject()").WithLocation(49, 17), // (39,17): warning CS8601: Possible null reference assignment. // T4 t4 = (T4)NullableObject(); // warn: T4 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T4)NullableObject()").WithLocation(39, 17), // (29,16): warning CS8601: Possible null reference assignment. // T3 t = (T3)NullableObject(); // warn: T3 may be non-null Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T3)NullableObject()").WithLocation(29, 16) ); } [Fact] public void UnconstrainedTypeParameter_MayBeNullable_01() { var source = @"class C { static void F(object o) { } static void F1(T1 t1) { F(t1); F((object)t1); t1.ToString(); } static void F2(T2 t2) where T2 : struct { F(t2); F((object)t2); t2.ToString(); } static void F3(T3 t3) where T3 : class { F(t3); F((object)t3); t3.ToString(); } static void F4(T4 t4) where T4 : new() { F(t4); F((object)t4); t4.ToString(); } static void F5(T5 t5) where T5 : I { F(t5); F((object)t5); t5.ToString(); } static void F6(T6 t6) where T6 : A { F(t6); F((object)t6); t6.ToString(); } } interface I { } class A { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F(t1); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t1").WithArguments("o", "void C.F(object o)").WithLocation(8, 11), // (9,11): warning CS8600: Converting null literal or possible null value to non-nullable type. // F((object)t1); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t1").WithLocation(9, 11), // (9,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F((object)t1); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(object)t1").WithArguments("o", "void C.F(object o)").WithLocation(9, 11), // (10,9): warning CS8602: Dereference of a possibly null reference. // t1.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(10, 9), // (26,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F(t4); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t4").WithArguments("o", "void C.F(object o)").WithLocation(26, 11), // (27,11): warning CS8600: Converting null literal or possible null value to non-nullable type. // F((object)t4); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t4").WithLocation(27, 11), // (27,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F((object)t4); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(object)t4").WithArguments("o", "void C.F(object o)").WithLocation(27, 11), // (28,9): warning CS8602: Dereference of a possibly null reference. // t4.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4").WithLocation(28, 9) ); } [Fact] public void UnconstrainedTypeParameter_MayBeNullable_02() { var source = @"class C { static void F1(T1 x1) { object? y1; y1 = (object?)x1; y1 = (object)x1; // warn: T1 may be null } static void F2(T2 x2) where T2 : class { object? y2; y2 = (object?)x2; y2 = (object)x2; } static void F3(T3 x3) where T3 : new() { object? y3; y3 = (object?)x3; y3 = (object)x3; // warn unless new() constraint implies non-nullable y3 = (object)new T3(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y1 = (object)x1; // warn: T1 may be null Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x1").WithLocation(7, 14), // (19,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y3 = (object)x3; // warn unless new() constraint implies non-nullable Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x3").WithLocation(19, 14) ); } [Fact] public void UnconstrainedTypeParameter_Return_01() { var source = @"class C { static object? F01(T t) => t; static object? F02(T t) where T : class => t; static object? F03(T t) where T : struct => t; static object? F04(T t) where T : new() => t; static object? F05(U u) where U : T => u; static object? F06(U u) where U : class, T => u; static object? F07(U u) where U : struct, T => u; static object? F08(U u) where U : T, new() => u; static object? F09(T t) => (object?)t; static object? F10(T t) where T : class => (object?)t; static object? F11(T t) where T : struct => (object?)t; static object? F12(T t) where T : new() => (object?)t; static object? F13(U u) where U : T => (object?)u; static object? F14(U u) where U : class, T => (object?)u; static object? F15(U u) where U : struct, T => (object?)u; static object? F16(U u) where U : T, new() => (object?)u; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void UnconstrainedTypeParameter_Return_02() { var source = @"class C { static object F01(T t) => t; static object F02(T t) where T : class => t; static object F03(T t) where T : struct => t; static object F04(T t) where T : new() => t; static object F05(U u) where U : T => u; static object F06(U u) where U : class, T => u; static object F07(U u) where U : struct, T => u; static object F08(U u) where U : T, new() => u; static object F09(T t) => (object)t; static object F10(T t) where T : class => (object)t; static object F11(T t) where T : struct => (object)t; static object F12(T t) where T : new() => (object)t; static object F13(U u) where U : T => (object)u; static object F14(U u) where U : class, T => (object)u; static object F15(U u) where U : struct, T => (object)u; static object F16(U u) where U : T, new() => (object)u; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,34): warning CS8603: Possible null reference return. // static object F01(T t) => t; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "t").WithLocation(3, 34), // (6,50): warning CS8603: Possible null reference return. // static object F04(T t) where T : new() => t; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "t").WithLocation(6, 50), // (7,49): warning CS8603: Possible null reference return. // static object F05(U u) where U : T => u; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "u").WithLocation(7, 49), // (10,56): warning CS8603: Possible null reference return. // static object F08(U u) where U : T, new() => u; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "u").WithLocation(10, 56), // (11,34): warning CS8600: Converting null literal or possible null value to non-nullable type. // static object F09(T t) => (object)t; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(11, 34), // (11,34): warning CS8603: Possible null reference return. // static object F09(T t) => (object)t; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(object)t").WithLocation(11, 34), // (14,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // static object F12(T t) where T : new() => (object)t; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(14, 50), // (14,50): warning CS8603: Possible null reference return. // static object F12(T t) where T : new() => (object)t; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(object)t").WithLocation(14, 50), // (15,49): warning CS8600: Converting null literal or possible null value to non-nullable type. // static object F13(U u) where U : T => (object)u; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)u").WithLocation(15, 49), // (15,49): warning CS8603: Possible null reference return. // static object F13(U u) where U : T => (object)u; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(object)u").WithLocation(15, 49), // (18,56): warning CS8600: Converting null literal or possible null value to non-nullable type. // static object F16(U u) where U : T, new() => (object)u; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)u").WithLocation(18, 56), // (18,56): warning CS8603: Possible null reference return. // static object F16(U u) where U : T, new() => (object)u; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(object)u").WithLocation(18, 56)); } [Fact] public void UnconstrainedTypeParameter_Return_03() { var source = @"class C { static T F01(T t) => t; static T F02(T t) where T : class => t; static T F03(T t) where T : struct => t; static T F04(T t) where T : new() => t; static T F05(U u) where U : T => u; static T F06(U u) where U : class, T => u; static T F07(U u) where U : struct, T => u; static T F08(U u) where U : T, new() => u; static T F09(T t) => (T)t; static T F10(T t) where T : class => (T)t; static T F11(T t) where T : struct => (T)t; static T F12(T t) where T : new() => (T)t; static T F13(U u) where U : T => (T)u; static T F14(U u) where U : class, T => (T)u; static T F15(U u) where U : struct, T => (T)u; static T F16(U u) where U : T, new() => (T)u; static U F17(T t) where U : T => (U)t; // W on cast static U F18(T t) where U : class, T => (U)t; // W on cast, W on return static U F19(T t) where U : struct, T => (U)t; static U F20(T t) where U : T, new() => (U)t; // W on cast static U F21(T t) => (U)(object)t; // W on cast, W on cast }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,44): warning CS8601: Possible null reference assignment. // static U F17(T t) where U : T => (U)t; // W on cast Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)t").WithLocation(19, 44), // (20,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F18(T t) where U : class, T => (U)t; // W on cast, W on return Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)t").WithLocation(20, 51), // (20,51): warning CS8603: Possible null reference return. // static U F18(T t) where U : class, T => (U)t; // W on cast, W on return Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)t").WithLocation(20, 51), // (21,52): warning CS8605: Unboxing a possibly null value. // static U F19(T t) where U : struct, T => (U)t; Diagnostic(ErrorCode.WRN_UnboxPossibleNull, "(U)t").WithLocation(21, 52), // (22,51): warning CS8601: Possible null reference assignment. // static U F20(T t) where U : T, new() => (U)t; // W on cast Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)t").WithLocation(22, 51), // (23,32): warning CS8601: Possible null reference assignment. // static U F21(T t) => (U)(object)t; // W on cast, W on cast Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)(object)t").WithLocation(23, 32), // (23,35): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F21(T t) => (U)(object)t; // W on cast, W on cast Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(23, 35) ); } [Fact] public void UnconstrainedTypeParameter_Uninitialized() { var source = @" class C { static void F1() { T t; t.ToString(); // 1 } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): error CS0165: Use of unassigned local variable 't' // t.ToString(); // 1 Diagnostic(ErrorCode.ERR_UseDefViolation, "t").WithArguments("t").WithLocation(7, 9) ); } [Fact] [WorkItem(29981, "https://github.com/dotnet/roslyn/issues/29981")] public void UnconstrainedTypeParameter_OutVariable() { var source = @" class C { static void F1(out T t) => t = default; // 1 static void F2(out T t) => t = default(T); // 2 static void F3(T t1, out T t2) => t2 = t1; static void F4(U u, out T t) where U : T => t = u; static void F5(U u, out T t) where T : U => t = (T)u; // 3 static void F6(U u, out T t) => t = (T)(object)u; // 4 } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,39): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // static void F1(out T t) => t = default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(4, 39), // (5,39): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // static void F2(out T t) => t = default(T); // 2 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(5, 39), // (8,59): warning CS8601: Possible null reference assignment. // static void F5(U u, out T t) where T : U => t = (T)u; // 3 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)u").WithLocation(8, 59), // (9,47): warning CS8601: Possible null reference assignment. // static void F6(U u, out T t) => t = (T)(object)u; // 4 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)(object)u").WithLocation(9, 47), // (9,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // static void F6(U u, out T t) => t = (T)(object)u; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)u").WithLocation(9, 50) ); } [Fact] [WorkItem(29983, "https://github.com/dotnet/roslyn/issues/29983")] public void UnconstrainedTypeParameter_TypeInferenceThroughCall() { var source = @" class C { static T Copy(T t) => t; static void CopyOut(T t1, out T t2) => t2 = t1; static void CopyOutInherit(T1 t1, out T2 t2) where T1 : T2 => t2 = t1; static void M(U u) { var x1 = Copy(u); x1.ToString(); // 1 CopyOut(u, out var x2); x2.ToString(); // 2 CopyOut(u, out U x3); x3.ToString(); // 3 if (u == null) throw null!; var x4 = Copy(u); x4.ToString(); CopyOut(u, out var x5); x5.ToString(); CopyOut(u, out U x6); x6.ToString(); CopyOutInherit(u, out var x7); x7.ToString(); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29983: Should not report warning for `x6.ToString()`. comp.VerifyDiagnostics( // (29,9): error CS0411: The type arguments for method 'C.CopyOutInherit(T1, out T2)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // CopyOutInherit(u, out var x7); Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "CopyOutInherit").WithArguments("C.CopyOutInherit(T1, out T2)").WithLocation(29, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(10, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(13, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // x3.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(16, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // x4.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4").WithLocation(21, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // x5.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x5").WithLocation(24, 9), // (27,9): warning CS8602: Dereference of a possibly null reference. // x6.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x6").WithLocation(27, 9)); } [Fact] [WorkItem(29993, "https://github.com/dotnet/roslyn/issues/29993")] public void TypeParameter_Return_01() { var source = @" class C { static U F1(T t) => (U)(object)t; // 1 and 2 static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 static U F3(T t) where U : struct => (U)(object)t; // 6 static U F4(T t) where T : class => (U)(object)t; static U F5(T t) where T : struct => (U)(object)t; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29993: Errors are different than expected. comp.VerifyDiagnostics( // (4,34): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F1(T t) => (U)(object)t; // 1 and 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(4, 34), // (4,31): warning CS8601: Possible null reference assignment. // static U F1(T t) => (U)(object)t; // 1 and 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)(object)t").WithLocation(4, 31), // (5,50): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(5, 50), // (5,47): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(U)(object)t").WithLocation(5, 47), // (5,47): warning CS8603: Possible null reference return. // static U F2(T t) where U : class => (U)(object)t; // 3, 4 and 5 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "(U)(object)t").WithLocation(5, 47), // (6,51): warning CS8600: Converting null literal or possible null value to non-nullable type. // static U F3(T t) where U : struct => (U)(object)t; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t").WithLocation(6, 51), // (6,48): warning CS8605: Unboxing a possibly null value. // static U F3(T t) where U : struct => (U)(object)t; // 6 Diagnostic(ErrorCode.WRN_UnboxPossibleNull, "(U)(object)t").WithLocation(6, 48) ); } [Fact] public void TrackUnconstrainedTypeParameter_LocalsAndParameters() { var source = @"class C { static void F0() { default(T).ToString(); // 1 default(T)?.ToString(); } static void F1() { T x1 = default; // 2 x1.ToString(); // 3 x1!.ToString(); x1?.ToString(); if (x1 != null) x1.ToString(); T y1 = x1; y1.ToString(); // 4 } static void F2(T x2, T[] a2) { x2.ToString(); // 5 x2!.ToString(); x2?.ToString(); if (x2 != null) x2.ToString(); T y2 = x2; y2.ToString(); // 6 a2[0].ToString(); // 7 } static void F3() where T : new() { T x3 = new T(); x3.ToString(); x3!.ToString(); var a3 = new[] { new T() }; a3[0].ToString(); // 8 } static T F4(T x4) { T y4 = x4; return y4; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // default(T).ToString(); // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(5, 9), // (5,9): warning CS8602: Dereference of a possibly null reference. // default(T).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T)").WithLocation(5, 9), // (6,9): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // default(T)?.ToString(); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 9), // (10,16): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // T x1 = default; // 2 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(10, 16), // (11,9): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(11, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(16, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(20, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. // y2.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(25, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // a2[0].ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2[0]").WithLocation(26, 9), // (34,9): warning CS8602: Dereference of a possibly null reference. // a3[0].ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a3[0]").WithLocation(34, 9) ); } [Fact] public void TrackUnconstrainedTypeParameter_ExplicitCast() { var source = @"class C { static void F(object o) { } static void F1(T1 t1) { F((object)t1); if (t1 != null) F((object)t1); } static void F2(T2 t2) where T2 : class { F((object)t2); if (t2 != null) F((object)t2); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,11): warning CS8600: Converting null literal or possible null value to non-nullable type. // F((object)t1); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t1").WithLocation(8, 11), // (8,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'. // F((object)t1); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(object)t1").WithArguments("o", "void C.F(object o)").WithLocation(8, 11) ); } [Fact] public void NullableT_BaseAndInterfaces() { var source = @"interface IA { } interface IB : IA { } interface IC { } class A { } class B : A<(T, T?)> { } class C : A, IA, IC { } class D : A, IA, IC { } class E : A, IA, IC { } class P { static void F1(IB o) { } static void F2(B o) { } static void F3(C o) { } static void F4(D o) { } static void F5(E o) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // interface IB : IA { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(2, 22), // (5,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class B : A<(T, T?)> { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 20), // (6,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C : A, IA, IC { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(6, 22), // (7,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class D : A, IA, IC { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(7, 29), // (8,36): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class E : A, IA, IC { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "V?").WithLocation(8, 36) ); } [Fact] public void NullableT_Constraints() { var source = @"interface I where U : T? { } class A { } class B { static void F() where U : A { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (1,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // interface I where U : T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(1, 29), // (5,39): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void F() where U : A { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 39) ); } [Fact] [WorkItem(29995, "https://github.com/dotnet/roslyn/issues/29995")] public void NullableT_Members() { var source = @"using System; #pragma warning disable 0067 #pragma warning disable 0169 #pragma warning disable 8618 delegate T? D(); class A { } class B { const object c = default(T?[]); T? F; B(T? t) { } static void M(T? t, U? u) { } static B P { get; set; } event EventHandler E; public static explicit operator A(B t) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/29995: Report error for `const object c = default(T?[]);`. comp.VerifyDiagnostics( // (5,10): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // delegate T? D(); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 10), // (11,30): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // const object c = default(T?[]); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(11, 30), // (12,5): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? F; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(12, 5), // (13,7): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // B(T? t) { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(13, 7), // (14,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void M(T? t, U? u) { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(14, 22), // (14,28): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void M(T? t, U? u) { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(14, 28), // (15,14): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static B P { get; set; } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(15, 14), // (16,24): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // event EventHandler E; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(16, 24), // (17,39): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public static explicit operator A(B t) => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(17, 39) ); } [Fact] public void NullableT_ReturnType() { var source = @"interface I { } class A { } class B { static T? F1() => throw null!; // error static T? F2() where T : class => throw null!; static T? F3() where T : struct => throw null!; static T? F4() where T : new() => throw null!; // error static T? F5() where T : unmanaged => throw null!; static T? F6() where T : I => throw null!; // error static T? F7() where T : A => throw null!; } class C { static U?[] F1() where U : T => throw null!; // error static U?[] F2() where T : class where U : T => throw null!; static U?[] F3() where T : struct where U : T => throw null!; static U?[] F4() where T : new() where U : T => throw null!; // error static U?[] F5() where T : unmanaged where U : T => throw null!; static U?[] F6() where T : I where U : T => throw null!; // error static U?[] F7() where T : A where U : T => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static U?[] F2() where T : class where U : T => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(16, 12), // (18,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static U?[] F4() where T : new() where U : T => throw null!; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(18, 12), // (20,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static U?[] F6() where T : I where U : T => throw null!; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(20, 12), // (15,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static U?[] F1() where U : T => throw null!; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(15, 12), // (17,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static U?[] F3() where T : struct where U : T => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(17, 12), // (17,23): error CS0456: Type parameter 'T' has the 'struct' constraint so 'T' cannot be used as a constraint for 'U' // static U?[] F3() where T : struct where U : T => throw null!; Diagnostic(ErrorCode.ERR_ConWithValCon, "U").WithArguments("U", "T").WithLocation(17, 23), // (19,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static U?[] F5() where T : unmanaged where U : T => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(19, 12), // (19,23): error CS8379: Type parameter 'T' has the 'unmanaged' constraint so 'T' cannot be used as a constraint for 'U' // static U?[] F5() where T : unmanaged where U : T => throw null!; Diagnostic(ErrorCode.ERR_ConWithUnmanagedCon, "U").WithArguments("U", "T").WithLocation(19, 23), // (8,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static T? F4() where T : new() => throw null!; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 12), // (10,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static T? F6() where T : I => throw null!; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(10, 12), // (5,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static T? F1() => throw null!; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 12)); } [Fact] public void NullableT_Parameters() { var source = @"interface I { } abstract class A { internal abstract void F1(T? t); // error internal abstract void F2(T? t) where T : class; internal abstract void F3(T? t) where T : struct; internal abstract void F4(T? t) where T : new(); // error internal abstract void F5(T? t) where T : unmanaged; internal abstract void F6(T? t) where T : I; // error internal abstract void F7(T? t) where T : A; } class B : A { internal override void F1(U? u) { } // error internal override void F2(U? u) { } internal override void F3(U? u) { } internal override void F4(U? u) { } // error internal override void F5(U? u) { } internal override void F6(U? u) { } // error internal override void F7(U? u) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,34): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // internal abstract void F1(T? t); // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 34), // (7,34): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // internal abstract void F4(T? t) where T : new(); // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 34), // (9,34): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // internal abstract void F6(T? t) where T : I; // error Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(9, 34), // (12,7): error CS0534: 'B' does not implement inherited abstract member 'A.F4(T?)' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F4(T?)").WithLocation(12, 7), // (12,7): error CS0534: 'B' does not implement inherited abstract member 'A.F1(T?)' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F1(T?)").WithLocation(12, 7), // (12,7): error CS0534: 'B' does not implement inherited abstract member 'A.F7(T?)' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F7(T?)").WithLocation(12, 7), // (12,7): error CS0534: 'B' does not implement inherited abstract member 'A.F2(T?)' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F2(T?)").WithLocation(12, 7), // (12,7): error CS0534: 'B' does not implement inherited abstract member 'A.F6(T?)' // class B : A Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F6(T?)").WithLocation(12, 7), // (14,28): error CS0115: 'B.F1(U?)': no suitable method found to override // internal override void F1(U? u) { } // error Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F1").WithArguments("B.F1(U?)").WithLocation(14, 28), // (14,37): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // internal override void F1(U? u) { } // error Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "u").WithArguments("System.Nullable", "T", "U").WithLocation(14, 37), // (15,28): error CS0115: 'B.F2(U?)': no suitable method found to override // internal override void F2(U? u) { } Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F2").WithArguments("B.F2(U?)").WithLocation(15, 28), // (15,37): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // internal override void F2(U? u) { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "u").WithArguments("System.Nullable", "T", "U").WithLocation(15, 37), // (17,28): error CS0115: 'B.F4(U?)': no suitable method found to override // internal override void F4(U? u) { } // error Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F4").WithArguments("B.F4(U?)").WithLocation(17, 28), // (17,37): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // internal override void F4(U? u) { } // error Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "u").WithArguments("System.Nullable", "T", "U").WithLocation(17, 37), // (19,28): error CS0115: 'B.F6(U?)': no suitable method found to override // internal override void F6(U? u) { } // error Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F6").WithArguments("B.F6(U?)").WithLocation(19, 28), // (19,37): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // internal override void F6(U? u) { } // error Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "u").WithArguments("System.Nullable", "T", "U").WithLocation(19, 37), // (20,28): error CS0115: 'B.F7(U?)': no suitable method found to override // internal override void F7(U? u) { } Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F7").WithArguments("B.F7(U?)").WithLocation(20, 28), // (20,37): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // internal override void F7(U? u) { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "u").WithArguments("System.Nullable", "T", "U").WithLocation(20, 37)); } [Fact] public void NullableT_ContainingType() { var source = @"class A { internal interface I { } internal enum E { } } class C { static void F1(A.I i) { } static void F2(A.E[] e) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void F2(A.E[] e) { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(9, 25), // (8,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void F1(A.I i) { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 25) ); } [Fact] public void NullableT_MethodBody() { var source = @"#pragma warning disable 0168 class C { static void M() { T? t; var u = typeof(U?); object? o = default(T?); o = new U?[0]; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? t; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(6, 9), // (7,24): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // var u = typeof(U?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(7, 24), // (8,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // object? o = default(T?); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 29), // (9,17): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // o = new U?[0]; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(9, 17) ); } [Fact] public void NullableT_Lambda() { var source = @"delegate void D(T t); class C { static void F(D d) { } static void G() { F((T? t) => { }); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // F((T? t) => { }); Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 12)); } [Fact] public void NullableT_LocalFunction() { var source = @"#pragma warning disable 8321 class C { static void F1() { T? L1() => throw null!; } static void F2() { void L2(T?[] t) { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? L1() => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(6, 9), // (10,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void L2(T?[] t) { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(10, 20)); } [Fact] [WorkItem(29996, "https://github.com/dotnet/roslyn/issues/29996")] public void NullableT_FromMetadata_BaseAndInterfaces() { var source0 = @".class public System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .method public hidebysig specialname rtspecialname instance void .ctor(bool[] b) cil managed { ret } } .class interface public abstract IA`1 { } .class interface public abstract IB`1 implements class IA`1 { .interfaceimpl type class IA`1 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(bool[]) = ( 01 00 02 00 00 00 00 01 00 00 ) } .class public A`1 { } .class public B`1 extends class A`1 { .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(bool[]) = ( 01 00 02 00 00 00 00 01 00 00 ) }"; var ref0 = CompileIL(source0); var source1 = @"class C { static void F(IB b) { } static void G(B b) { } }"; var comp = CreateCompilation(source1, new[] { ref0 }); // https://github.com/dotnet/roslyn/issues/29996: Report errors for T? in metadata? comp.VerifyDiagnostics(); } [Fact] [WorkItem(29996, "https://github.com/dotnet/roslyn/issues/29996")] public void NullableT_FromMetadata_Methods() { var source0 = @".class public System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .class interface public abstract I { } .class public A { } .class public C { .method public static !!T F1() { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) ldnull throw } .method public static !!T F2() { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) ldnull throw } .method public static !!T F3() { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) ldnull throw } .method public static !!T F4<.ctor T>() { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) ldnull throw } .method public static !!T F5<(I) T>() { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) ldnull throw } .method public static !!T F6<(A) T>() { .param [0] .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) ldnull throw } }"; var ref0 = CompileIL(source0); var source1 = @"class P { static void Main() { C.F1(); // error C.F1(); C.F2(); C.F3(); C.F4(); // error C.F5(); // error C.F6(); } }"; var comp = CreateCompilation(source1, new[] { ref0 }); // https://github.com/dotnet/roslyn/issues/29996: Report errors for T? in metadata? comp.VerifyDiagnostics(); } [WorkItem(27289, "https://github.com/dotnet/roslyn/issues/27289")] [Fact] public void NullableTInConstraint_01() { var source = @"class A { } class B where T : T? { } class C where T : class, T? { } class D where T : struct, T? { } class E where T : A, T? { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,30): error CS0701: 'T?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // class D where T : struct, T? { } Diagnostic(ErrorCode.ERR_BadBoundType, "T?").WithArguments("T?").WithLocation(4, 30), // (2,9): error CS0454: Circular constraint dependency involving 'T' and 'T' // class B where T : T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(2, 9), // (2,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class B where T : T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(2, 22), // (3,9): error CS0454: Circular constraint dependency involving 'T' and 'T' // class C where T : class, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(3, 9), // (5,9): error CS0454: Circular constraint dependency involving 'T' and 'T' // class E where T : A, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(5, 9)); } [WorkItem(27289, "https://github.com/dotnet/roslyn/issues/27289")] [Fact] public void NullableTInConstraint_02() { var source = @"class A where U : T? { } class B where T : class where U : T? { } class C where T : U? where U : T? { } class D where T : class, U? where U : class, T? { } class E where T : class, U where U : T? { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,15): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // where U : T? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(2, 15), // (11,15): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // where T : U? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(11, 15), // (12,15): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // where U : T? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(12, 15), // (10,9): error CS0454: Circular constraint dependency involving 'T' and 'U' // class C Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "U").WithLocation(10, 9), // (15,9): error CS0454: Circular constraint dependency involving 'T' and 'U' // class D Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "U").WithLocation(15, 9), // (20,9): error CS0454: Circular constraint dependency involving 'T' and 'U' // class E Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "U").WithLocation(20, 9)); } [WorkItem(27289, "https://github.com/dotnet/roslyn/issues/27289")] [Fact] public void NullableTInConstraint_03() { var source = @"class A where T : T, T? { } class B where U : U?, U { } class C where V : V?, V? { } delegate void D1() where U1 : T1, T1?; delegate void D2() where U2 : class, T2?, T2; delegate void D3() where T3 : class where U3 : T3, T3?;"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (1,25): error CS0405: Duplicate constraint 'T' for type parameter 'T' // class A where T : T, T? { } Diagnostic(ErrorCode.ERR_DuplicateBound, "T?").WithArguments("T", "T").WithLocation(1, 25), // (1,25): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class A where T : T, T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(1, 25), // (1,9): error CS0454: Circular constraint dependency involving 'T' and 'T' // class A where T : T, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(1, 9), // (2,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class B where U : U?, U { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(2, 22), // (2,26): error CS0405: Duplicate constraint 'U' for type parameter 'U' // class B where U : U?, U { } Diagnostic(ErrorCode.ERR_DuplicateBound, "U").WithArguments("U", "U").WithLocation(2, 26), // (2,9): error CS0454: Circular constraint dependency involving 'U' and 'U' // class B where U : U?, U { } Diagnostic(ErrorCode.ERR_CircularConstraint, "U").WithArguments("U", "U").WithLocation(2, 9), // (3,22): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C where V : V?, V? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "V?").WithLocation(3, 22), // (3,26): error CS0405: Duplicate constraint 'V' for type parameter 'V' // class C where V : V?, V? { } Diagnostic(ErrorCode.ERR_DuplicateBound, "V?").WithArguments("V", "V").WithLocation(3, 26), // (3,26): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C where V : V?, V? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "V?").WithLocation(3, 26), // (3,9): error CS0454: Circular constraint dependency involving 'V' and 'V' // class C where V : V?, V? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "V").WithArguments("V", "V").WithLocation(3, 9), // (5,20): error CS0405: Duplicate constraint 'T1' for type parameter 'U1' // where U1 : T1, T1?; Diagnostic(ErrorCode.ERR_DuplicateBound, "T1?").WithArguments("T1", "U1").WithLocation(5, 20), // (5,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // where U1 : T1, T1?; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T1?").WithLocation(5, 20), // (7,23): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // where U2 : class, T2?, T2; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T2?").WithLocation(7, 23), // (7,28): error CS0405: Duplicate constraint 'T2' for type parameter 'U2' // where U2 : class, T2?, T2; Diagnostic(ErrorCode.ERR_DuplicateBound, "T2").WithArguments("T2", "U2").WithLocation(7, 28), // (10,20): error CS0405: Duplicate constraint 'T3' for type parameter 'U3' // where U3 : T3, T3?; Diagnostic(ErrorCode.ERR_DuplicateBound, "T3?").WithArguments("T3", "U3").WithLocation(10, 20)); } [Fact] public void NullableTInConstraint_04() { var source = @"class A { } class B { static void F1() where T : T? { } static void F2() where T : class, T? { } static void F3() where T : struct, T? { } static void F4() where T : A, T? { } static void F5() where U : T? { } static void F6() where T : class where U : T? { } static void F7() where T : struct where U : T? { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): error CS0454: Circular constraint dependency involving 'T' and 'T' // static void F2() where T : class, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(5, 20), // (6,43): error CS0701: 'T?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // static void F3() where T : struct, T? { } Diagnostic(ErrorCode.ERR_BadBoundType, "T?").WithArguments("T?").WithLocation(6, 43), // (7,20): error CS0454: Circular constraint dependency involving 'T' and 'T' // static void F4() where T : A, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(7, 20), // (8,38): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void F5() where U : T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 38), // (10,55): error CS0701: 'T?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // static void F7() where T : struct where U : T? { } Diagnostic(ErrorCode.ERR_BadBoundType, "T?").WithArguments("T?").WithLocation(10, 55), // (4,35): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // static void F1() where T : T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 35), // (4,20): error CS0454: Circular constraint dependency involving 'T' and 'T' // static void F1() where T : T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(4, 20)); } [Fact] public void NullableTInConstraint_05() { var source = @"#pragma warning disable 8321 class A { } class B { static void M() { void F1() where T : T? { } void F2() where T : class, T? { } void F3() where T : struct, T? { } void F4() where T : A, T? { } void F5() where U : T? { } void F6() where T : class where U : T? { } void F7() where T : struct where U : T? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,32): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F1() where T : T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 32), // (7,17): error CS0454: Circular constraint dependency involving 'T' and 'T' // void F1() where T : T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(7, 17), // (8,17): error CS0454: Circular constraint dependency involving 'T' and 'T' // void F2() where T : class, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(8, 17), // (9,40): error CS0701: 'T?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // void F3() where T : struct, T? { } Diagnostic(ErrorCode.ERR_BadBoundType, "T?").WithArguments("T?").WithLocation(9, 40), // (10,17): error CS0454: Circular constraint dependency involving 'T' and 'T' // void F4() where T : A, T? { } Diagnostic(ErrorCode.ERR_CircularConstraint, "T").WithArguments("T", "T").WithLocation(10, 17), // (11,35): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void F5() where U : T? { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(11, 35), // (13,52): error CS0701: 'T?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. // void F7() where T : struct where U : T? { } Diagnostic(ErrorCode.ERR_BadBoundType, "T?").WithArguments("T?").WithLocation(13, 52)); } [Fact] public void NullableTInConstraint_06() { var source = @"#pragma warning disable 8321 class A where T : class { static void F1() where U : T? { } static void F2() { void F3() where U : T? { } } } class B { static void F4() where T : class { void F5() where U : T? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableTInConstraint_07() { var source = @"interface I where T : class where U : T { } class A where T : class where U : T? { } class B1 : A, I where T : class { } class B2 : A, I where T : class { } class B3 : A, I where T : class { } class B4 : A, I where T : class { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,7): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'I'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // class B2 : A, I Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "B2").WithArguments("I", "T", "U", "T?").WithLocation(15, 7), // (19,7): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'T?' doesn't match 'class' constraint. // class B3 : A, I Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "B3").WithArguments("A", "T", "T?").WithLocation(19, 7), // (19,7): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'I'. Nullability of type argument 'T?' doesn't match 'class' constraint. // class B3 : A, I Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "B3").WithArguments("I", "T", "T?").WithLocation(19, 7), // (23,7): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'T?' doesn't match 'class' constraint. // class B4 : A, I Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "B4").WithArguments("A", "T", "T?").WithLocation(23, 7), // (23,7): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'I'. Nullability of type argument 'T?' doesn't match 'class' constraint. // class B4 : A, I Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "B4").WithArguments("I", "T", "T?").WithLocation(23, 7)); } // `class C where T : class, T?` from metadata. [Fact] public void NullableTInConstraint_08() { // https://github.com/dotnet/roslyn/issues/29997: `where T : class, T?` is not valid in C#, // so the class needs to be defined in IL. How and where should the custom // attribute be declared for the constraint type in the following? var source0 = @".class public System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor() = ( 01 00 00 00 ) .class public C { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } }"; var ref0 = CompileIL(source0); var source1 = @"class Program { static void Main() { object o; o = new C(); // 1 o = new C(); // 2 } }"; var comp = CreateCompilation(new[] { source1 }, new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,19): error CS0454: Circular constraint dependency involving 'T' and 'T' // o = new C(); // 1 Diagnostic(ErrorCode.ERR_CircularConstraint, "object?").WithArguments("T", "T").WithLocation(6, 19), // (7,19): error CS0454: Circular constraint dependency involving 'T' and 'T' // o = new C(); // 2 Diagnostic(ErrorCode.ERR_CircularConstraint, "object").WithArguments("T", "T").WithLocation(7, 19)); } // `class C where U : T?` from metadata. [Fact] public void NullableTInConstraint_09() { var source0 = @"public class C where T : class where U : T? { }"; var source1 = @"class Program { static void Main() { object o; o = new C(); // 1 o = new C(); // 2 o = new C(); // 3 o = new C(); // 4 } }"; var comp = CreateCompilation(source0); comp.VerifyDiagnostics( // (3,15): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // where U : T? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(3, 15), // (3,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // where U : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 16) ); MetadataReference ref0 = comp.ToMetadataReference(); comp = CreateCompilation(new[] { source1 }, new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); ref0 = comp.EmitToImageReference(); comp = CreateCompilation(new[] { source1 }, new[] { ref0 }, options: WithNonNullTypesTrue()); var c = comp.GetTypeByMetadataName("C`2"); Assert.IsAssignableFrom(c); Assert.Equal("C where T : class! where U : T?", c.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); comp.VerifyDiagnostics( // (6,19): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // o = new C(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(6, 19), // (7,19): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C'. Nullability of type argument 'object?' doesn't match 'class' constraint. // o = new C(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C", "T", "object?").WithLocation(7, 19) ); } [WorkItem(26294, "https://github.com/dotnet/roslyn/issues/26294")] [Fact] public void NullableTInConstraint_10() { var source = @"interface I { } class C { static void F1() where T : class, I { } static void F2() where T : I { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,35): error CS1968: Constraint cannot be a dynamic type 'I' // static void F2() where T : I { } Diagnostic(ErrorCode.ERR_ConstructedDynamicTypeAsBound, "I").WithArguments("I").WithLocation(5, 35)); } [Fact] public void DuplicateConstraints() { var source = @"interface I where T : class { } class C where T : class { static void F1() where U : T, T { } static void F2() where U : T, T? { } static void F3() where U : T?, T { } static void F4() where U : T?, T? { } static void F5() where U : I, I { } static void F6() where U : I, I { } static void F7() where U : I, I { } static void F8() where U : I, I { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,38): error CS0405: Duplicate constraint 'T' for type parameter 'U' // static void F1() where U : T, T { } Diagnostic(ErrorCode.ERR_DuplicateBound, "T").WithArguments("T", "U").WithLocation(4, 38), // (5,38): error CS0405: Duplicate constraint 'T' for type parameter 'U' // static void F2() where U : T, T? { } Diagnostic(ErrorCode.ERR_DuplicateBound, "T?").WithArguments("T", "U").WithLocation(5, 38), // (6,39): error CS0405: Duplicate constraint 'T' for type parameter 'U' // static void F3() where U : T?, T { } Diagnostic(ErrorCode.ERR_DuplicateBound, "T").WithArguments("T", "U").WithLocation(6, 39), // (7,39): error CS0405: Duplicate constraint 'T' for type parameter 'U' // static void F4() where U : T?, T? { } Diagnostic(ErrorCode.ERR_DuplicateBound, "T?").WithArguments("T", "U").WithLocation(7, 39), // (8,41): error CS0405: Duplicate constraint 'I' for type parameter 'U' // static void F5() where U : I, I { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I").WithArguments("I", "U").WithLocation(8, 41), // (9,41): error CS0405: Duplicate constraint 'I' for type parameter 'U' // static void F6() where U : I, I { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I").WithArguments("I", "U").WithLocation(9, 41), // (10,20): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'I'. Nullability of type argument 'T?' doesn't match 'class' constraint. // static void F7() where U : I, I { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "U").WithArguments("I", "T", "T?").WithLocation(10, 20), // (10,42): error CS0405: Duplicate constraint 'I' for type parameter 'U' // static void F7() where U : I, I { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I").WithArguments("I", "U").WithLocation(10, 42), // (11,20): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'I'. Nullability of type argument 'T?' doesn't match 'class' constraint. // static void F8() where U : I, I { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "U").WithArguments("I", "T", "T?").WithLocation(11, 20), // (11,42): error CS0405: Duplicate constraint 'I' for type parameter 'U' // static void F8() where U : I, I { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I").WithArguments("I", "U").WithLocation(11, 42)); } [Fact] public void PartialClassConstraints() { var source = @"class A where T : A where U : B { } partial class B where T : A where U : B { } partial class B where T : A where U : B { }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void PartialClassConstraintMismatch() { var source = @"class A { } partial class B where T : A { } partial class B where T : A? { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,15): error CS0265: Partial declarations of 'B' have inconsistent constraints for type parameter 'T' // partial class B where T : A { } Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "B").WithArguments("B", "T").WithLocation(2, 15)); } [Fact] public void TypeUnification_01() { var source = @"interface I { } class C1 : I, I { } class C2 : I, I { } class C3 : I, I { } class C4 : I, I { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,7): error CS0695: 'C1' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C1 : I, I { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C1").WithArguments("C1", "I", "I").WithLocation(2, 7), // (3,7): error CS0695: 'C2' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C2 : I, I { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2", "I", "I").WithLocation(3, 7), // (4,7): error CS0695: 'C3' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C3 : I, I { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3", "I", "I").WithLocation(4, 7), // (5,7): error CS0695: 'C4' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C4 : I, I { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4", "I", "I").WithLocation(5, 7), // (4,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C3 : I, I { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 20), // (5,20): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C4 : I, I { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(5, 20), // (5,27): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C4 : I, I { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(5, 27), // (3,26): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C2 : I, I { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(3, 26) ); } [Fact] public void TypeUnification_02() { var source = @"interface I { } class C1 : I, I where T : struct { } class C2 : I, I where T : struct { } class C3 : I, I where T : struct { } class C4 : I, I where T : struct { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,7): error CS0695: 'C1' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C1 : I, I where T : struct { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C1").WithArguments("C1", "I", "I").WithLocation(2, 7), // (3,7): error CS0695: 'C2' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C2 : I, I where T : struct { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2", "I", "I").WithLocation(3, 7), // (3,26): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C2 : I, I where T : class { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(3, 26), // (4,7): error CS0695: 'C3' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C3 : I, I where T : struct { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3", "I", "I").WithLocation(4, 7), // (5,7): error CS0695: 'C4' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C4 : I, I where T : struct { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4", "I", "I").WithLocation(5, 7), // (5,27): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C4 : I, I where T : class { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(5, 27) ); } [Fact] public void TypeUnification_03() { var source = @"interface I { } class C1 : I, I where T : class { } class C2 : I, I where T : class { } class C3 : I, I where T : class { } class C4 : I, I where T : class { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,7): error CS0695: 'C1' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C1 : I, I where T : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C1").WithArguments("C1", "I", "I").WithLocation(2, 7), // (3,7): error CS0695: 'C2' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C2 : I, I where T : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2", "I", "I").WithLocation(3, 7), // (3,26): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C2 : I, I where T : class { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(3, 26), // (4,7): error CS0695: 'C3' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C3 : I, I where T : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3", "I", "I").WithLocation(4, 7), // (5,7): error CS0695: 'C4' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C4 : I, I where T : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4", "I", "I").WithLocation(5, 7), // (5,27): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class C4 : I, I where T : class { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(5, 27) ); } [Fact] public void TypeUnification_04() { var source = @"interface I { } class C1 : I, I where T : struct where U : class { } class C2 : I, I where T : struct where U : class { } class C3 : I, I where T : struct where U : class { } class C4 : I, I where T : struct where U : class { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // Constraints are ignored when unifying types. comp.VerifyDiagnostics( // (2,7): error CS0695: 'C1' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C1 : I, I where T : struct where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C1").WithArguments("C1", "I", "I").WithLocation(2, 7), // (3,7): error CS0695: 'C2' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C2 : I, I where T : struct where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2", "I", "I").WithLocation(3, 7), // (4,7): error CS0695: 'C3' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C3 : I, I where T : struct where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3", "I", "I").WithLocation(4, 7), // (5,7): error CS0695: 'C4' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C4 : I, I where T : struct where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4", "I", "I").WithLocation(5, 7)); } [Fact] public void TypeUnification_05() { var source = @"interface I where T : class? { } class C1 : I, I where T : class where U : class { } class C2 : I, I where T : class where U : class { } class C3 : I, I where T : class where U : class { } class C4 : I, I where T : class where U : class { }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (2,7): error CS0695: 'C1' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C1 : I, I where T : class where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C1").WithArguments("C1", "I", "I").WithLocation(2, 7), // (3,7): error CS0695: 'C2' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C2 : I, I where T : class where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C2").WithArguments("C2", "I", "I").WithLocation(3, 7), // (4,7): error CS0695: 'C3' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C3 : I, I where T : class where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C3").WithArguments("C3", "I", "I").WithLocation(4, 7), // (5,7): error CS0695: 'C4' cannot implement both 'I' and 'I' because they may unify for some type parameter substitutions // class C4 : I, I where T : class where U : class { } Diagnostic(ErrorCode.ERR_UnifyingInterfaceInstantiations, "C4").WithArguments("C4", "I", "I").WithLocation(5, 7)); } [Fact] public void AssignmentNullability() { var source = @"class C { static void F1(string? x1, string y1) { object? z1; (z1 = x1).ToString(); (z1 = y1).ToString(); } static void F2(string? x2, string y2) { object z2; (z2 = x2).ToString(); (z2 = y2).ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (z1 = x1).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1 = x1").WithLocation(6, 10), // (12,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // (z2 = x2).ToString(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x2").WithLocation(12, 15), // (12,10): warning CS8602: Dereference of a possibly null reference. // (z2 = x2).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2 = x2").WithLocation(12, 10)); } [WorkItem(27008, "https://github.com/dotnet/roslyn/issues/27008")] [Fact] public void OverriddenMethodNullableValueTypeParameter_01() { var source0 = @"public abstract class A { public abstract void F(int? i); }"; var comp0 = CreateCompilation(source0); var ref0 = comp0.EmitToImageReference(); var source = @"class B : A { public override void F(int? i) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); } [Fact] public void OverriddenMethodNullableValueTypeParameter_02() { var source0 = @"public abstract class A where T : struct { public abstract void F(T? t); }"; var comp0 = CreateCompilation(source0); var ref0 = comp0.EmitToImageReference(); var source = @"class B1 : A where T : struct { public override void F(T? t) { } } class B2 : A { public override void F(int? t) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); } [WorkItem(27967, "https://github.com/dotnet/roslyn/issues/27967")] [Fact] public void UnannotatedTypeArgument_Interface() { var source0 = @"public interface I { } public class B : I { } public class C : I { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class Program { static void F(B x) { I a = x; I b = x; } static void F(C y) { I a = y; I b = y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); } [WorkItem(27967, "https://github.com/dotnet/roslyn/issues/27967")] [Fact] public void UnannotatedTypeArgument_BaseType() { var source0 = @"public class A { } public class B : A { } public class C : A { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class Program { static void F(B x) { A a = x; A b = x; } static void F(C y) { A a = y; A b = y; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); } [Fact] public void UnannotatedTypeArgument_Interface_Lookup() { var source0 = @"public interface I { void F(T t); } public interface I1 : I { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"interface I2 : I { } class Program { static void F(I1 i1, I2 i2, object x, object? y) { i1.F(x); i1.F(y); i2.F(x); i2.F(y); // warn } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (11,14): warning CS8604: Possible null reference argument for parameter 't' in 'void I.F(object t)'. // i2.F(y); // warn Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "void I.F(object t)").WithLocation(11, 14)); } [Fact] public void UnannotatedTypeArgument_BaseType_Lookup() { var source0 = @"public class A { public static void F(T t) { } } public class B1 : A { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class B2 : A { } class Program { static void F(object x, object? y) { B1.F(x); B1.F(y); B2.F(x); B2.F(y); // warn } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (11,14): warning CS8604: Possible null reference argument for parameter 't' in 'void A.F(object t)'. // B2.F(y); // warn Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "void A.F(object t)").WithLocation(11, 14)); } [Fact] public void UnannotatedConstraint_01() { var source0 = @"public class A1 { } public class A2 { } public class B1 where T : A1 { } public class B2 where T : A2 { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class Program { static void Main() { new B1(); new B1(); new B2>(); new B2>(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); var typeParameters = comp.GetMember("B1").TypeParameters; Assert.Equal("A1", typeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); typeParameters = comp.GetMember("B2").TypeParameters; Assert.Equal("A2", typeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } [Fact] public void UnannotatedConstraint_02() { var source0 = @" public class A1 { } public class A2 { } #nullable disable public class B1 where T : A1 where U : A1? { } #nullable disable public class B2 where T : A2 where U : A2 { }"; var comp0 = CreateCompilation(new[] { source0 }); comp0.VerifyDiagnostics( // (5,48): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public class B1 where T : A1 where U : A1? { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 48), // (7,63): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public class B2 where T : A2 where U : A2 { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 63) ); var ref0 = comp0.EmitToImageReference(); var source = @"class Program { static void Main() { new B1(); new B1(); new B2, A2>(); new B2, A2>(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (8,29): warning CS8631: The type 'A2' cannot be used as type parameter 'U' in the generic type or method 'B2'. Nullability of type argument 'A2' doesn't match constraint type 'A2'. // new B2, A2>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A2").WithArguments("B2", "A2", "U", "A2").WithLocation(8, 29)); var typeParameters = comp.GetMember("B1").TypeParameters; Assert.Equal("A1", typeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); Assert.Equal("A1?", typeParameters[1].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); typeParameters = comp.GetMember("B2").TypeParameters; Assert.Equal("A2", typeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); Assert.Equal("A2", typeParameters[1].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } [Fact] public void UnannotatedConstraint_Override() { var source0 = @" public interface I { } public abstract class A where T : class { #nullable disable public abstract void F1() where U : T, I; #nullable disable public abstract void F2() where U : T?, I; #nullable enable public abstract void F3() where U : T, I; #nullable enable public abstract void F4() where U : T?, I; }"; var comp0 = CreateCompilation(new[] { source0 }); comp0.VerifyDiagnostics( // (8,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract void F2() where U : T?, I; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 45), // (8,44): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public abstract void F2() where U : T?, I; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 44), // (8,51): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract void F2() where U : T?, I; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 51), // (8,50): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public abstract void F2() where U : T?, I; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 50), // (12,44): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public abstract void F4() where U : T?, I; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(12, 44), // (12,50): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public abstract void F4() where U : T?, I; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(12, 50) ); var source = @" #nullable disable class B1 : A { public override void F1() { } public override void F2() { } public override void F3() { } public override void F4() { } } #nullable disable class B2 : A { public override void F1() { } public override void F2() { } public override void F3() { } public override void F4() { } } #nullable enable class B3 : A { public override void F1() { } public override void F2() { } public override void F3() { } public override void F4() { } } #nullable enable class B4 : A { public override void F1() { } public override void F2() { } public override void F3() { } public override void F4() { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { new CSharpCompilationReference(comp0) }); comp.VerifyDiagnostics( // (11,20): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B2 : A Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 20) ); verifyAllConstraintTypes(); comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics( // (8,45): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract void F2() where U : T?, I; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 45), // (8,51): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public abstract void F2() where U : T?, I; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 51) ); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { new CSharpCompilationReference(comp0) }); comp.VerifyDiagnostics( // (11,20): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B2 : A Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 20), // (27,7): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'string?' doesn't match 'class' constraint. // class B4 : A Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "B4").WithArguments("A", "T", "string?").WithLocation(27, 7) ); verifyAllConstraintTypes(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { comp0.EmitToImageReference() }); comp.VerifyDiagnostics( // (11,20): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B2 : A Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(11, 20), // (27,7): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'string?' doesn't match 'class' constraint. // class B4 : A Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "B4").WithArguments("A", "T", "string?").WithLocation(27, 7) ); verifyAllConstraintTypes(); void verifyAllConstraintTypes() { string bangOrEmpty = comp0.Options.NullableContextOptions == NullableContextOptions.Disable ? "" : "!"; verifyConstraintTypes("B1.F1", "System.String", "I"); verifyConstraintTypes("B1.F2", "System.String?", "I"); verifyConstraintTypes("B1.F3", "System.String" + bangOrEmpty, "I!"); verifyConstraintTypes("B1.F4", "System.String?", "I!"); verifyConstraintTypes("B2.F1", "System.String?", "I"); verifyConstraintTypes("B2.F2", "System.String?", "I"); verifyConstraintTypes("B2.F3", "System.String?", "I!"); verifyConstraintTypes("B2.F4", "System.String?", "I!"); verifyConstraintTypes("B3.F1", "System.String!", "I"); verifyConstraintTypes("B3.F2", "System.String?", "I"); verifyConstraintTypes("B3.F3", "System.String!", "I!"); verifyConstraintTypes("B3.F4", "System.String?", "I!"); verifyConstraintTypes("B4.F1", "System.String?", "I"); verifyConstraintTypes("B4.F2", "System.String?", "I"); verifyConstraintTypes("B4.F3", "System.String?", "I!"); verifyConstraintTypes("B4.F4", "System.String?", "I!"); } void verifyConstraintTypes(string methodName, params string[] expectedTypes) { var constraintTypes = comp.GetMember(methodName).TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics; AssertEx.Equal(expectedTypes, constraintTypes.SelectAsArray(t => t.ToTestDisplayString(true))); } } [Fact] public void Constraint_LocalFunction_01() { var source = @" class C { #nullable enable void M1() { local(new C(), new C(), new C(), null); void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? { T? x = t; x!.ToString(); } } #nullable disable void M2() { local(new C(), new C(), new C(), null); void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? { T? x = t; // warn 1 x!.ToString(); } } }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (18,56): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 56), // (18,85): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 85), // (18,99): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(18, 99), // (18,98): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(18, 98), // (20,13): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? x = t; // warn 1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(20, 13), // (20,14): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? x = t; // warn 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(20, 14) ); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var localSyntaxes = tree.GetRoot().DescendantNodes().OfType(); verifyLocalFunction(localSyntaxes.ElementAt(0), "C.M1.local", new[] { "C!" }); verifyLocalFunction(localSyntaxes.ElementAt(1), "C.M2.local", new[] { "C" }); void verifyLocalFunction(LocalFunctionStatementSyntax localSyntax, string expectedName, string[] expectedConstraintTypes) { var localSymbol = (LocalFunctionSymbol)model.GetDeclaredSymbol(localSyntax); var constraintTypes = localSymbol.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics; AssertEx.Equal(expectedConstraintTypes, constraintTypes.SelectAsArray(t => t.ToTestDisplayString(true))); } } [Fact] public void Constraint_LocalFunction_02() { var source = @" class C { void M3() { local(new C(), new C(), new C(), null); void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? { T? x = t; // warn 2 x!.ToString(); // warn 3 } } }"; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (7,56): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 56), // (7,85): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 85), // (7,99): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(7, 99), // (7,98): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void local(T t, T2 t2, T3 t3, string? s) where T : C where T2 : C? where T3 : T? Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(7, 98), // (9,14): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // T? x = t; // warn 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 14), // (9,13): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // T? x = t; // warn 2 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(9, 13) ); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var localSyntaxes = tree.GetRoot().DescendantNodes().OfType(); verifyLocalFunction(localSyntaxes.ElementAt(0), "C.M3.local", new[] { "C" }); void verifyLocalFunction(LocalFunctionStatementSyntax localSyntax, string expectedName, string[] expectedConstraintTypes) { var localSymbol = (LocalFunctionSymbol)model.GetDeclaredSymbol(localSyntax); var constraintTypes = localSymbol.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics; AssertEx.Equal(expectedConstraintTypes, constraintTypes.SelectAsArray(t => t.ToTestDisplayString(true))); } } [Fact] public void Constraint_Oblivious_01() { var source0 = @"public interface I { } public class A where T : I { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); var ref0 = comp0.EmitToImageReference(); var source = @"using System; class B1 : I { } class B2 : I { } class C { static void Main() { Type t; t = typeof(A); t = typeof(A); // 1 t = typeof(A); // 2 t = typeof(A); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (10,22): warning CS8631: The type 'B2' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'B2' doesn't match constraint type 'I'. // t = typeof(A); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "B2").WithArguments("A", "I", "T", "B2").WithLocation(10, 22), // (11,22): warning CS8631: The type 'B1?' cannot be used as type parameter 'T' in the generic type or method 'A'. Nullability of type argument 'B1?' doesn't match constraint type 'I'. // t = typeof(A); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "B1?").WithArguments("A", "I", "T", "B1?").WithLocation(11, 22)); var constraintTypes = comp.GetMember("A").TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics; Assert.Equal("I", constraintTypes[0].ToTestDisplayString(true)); } [Fact] public void Constraint_Oblivious_02() { var source0 = @"public class A where T : A where V : U { protected interface I { } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); var ref0 = comp0.EmitToImageReference(); var source = @"class B : A { static void F(I i) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics(); } [Fact] public void Constraint_Oblivious_03() { var source0 = @"public class A { } public class B0 where T : A { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"#pragma warning disable 0169 class B1 where T : A? { } class B2 where T : A { } #nullable enable class B3 where T : A? { } #nullable enable class B4 where T : A { } #nullable disable class C { B0 F1; // 1 B0 F2; B1 F3; // 2 B1 F4; B2 F5; // 3 B2 F6; B3 F7; // 4 B3 F8; B4 F9; // 5 and 6 B4 F10; } #nullable enable class D { B0 G1; B0 G2; B1 G3; B1 G4; B2 G5; B2 G6; B3 G7; B3 G8; B4 G9; // 7 B4 G10; }"; var comp = CreateCompilation(new[] { source }, references: new[] { ref0 }); comp.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_UninitializedNonNullableField).Verify( // (15,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B1 F3; // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 9), // (4,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B1 where T : A? { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 24), // (17,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B2 F5; // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 9), // (19,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B3 F7; // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 9), // (35,12): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // B4 G9; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A?").WithLocation(35, 12), // (21,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B4 F9; // 5 and 6 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 9), // (13,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B0 F1; // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 9) ); } [Fact] public void Constraint_Oblivious_04() { var source0 = @"public class A { } public class B0 where T : A { }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"#pragma warning disable 0169 class B1 where T : A { } class B2 where T : A { } #nullable enable class B3 where T : A { } #nullable enable class B4 where T : A { } #nullable disable class C { B0> F1; // 1 B0> F2; B1> F3; // 2 B1> F4; B2> F5; // 3 B2> F6; B3> F7; // 4 B3> F8; B4> F9; // 5 and 6 B4> F10; } #nullable enable class D { B0> G1; B0> G2; B1> G3; B1> G4; // 7 B2> G5; B2> G6; B3> G7; B3> G8; // 8 B4> G9; // 9 B4> G10; }"; var comp = CreateCompilation(new[] { source }, references: new[] { ref0 }); comp.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_UninitializedNonNullableField).Verify( // (4,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B1 where T : A { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 31), // (15,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B1> F3; // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 16), // (17,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B2> F5; // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 16), // (19,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B3> F7; // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 16), // (21,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B4> F9; // 5 and 6 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 16), // (13,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B0> F1; // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 16), // (30,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B1'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B1> G4; // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G4").WithArguments("B1", "A", "T", "A").WithLocation(30, 19), // (34,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B3'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B3> G8; // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G8").WithArguments("B3", "A", "T", "A").WithLocation(34, 19), // (35,20): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B4> G9; // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A").WithLocation(35, 20) ); } [Fact] public void Constraint_TypeParameterConstraint() { var source0 = @"public class A1 where T : class where U : class, T { } public class A2 where T : class where U : class, T? { }"; var comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @" class B1 where T : A1 { } // 1 class B2 where T : A2 { } // 2 #nullable enable class B3 where T : A1 { } #nullable enable class B4 where T : A2 { }"; var comp = CreateCompilation(new[] { source }, references: new[] { ref0 }); comp.VerifyDiagnostics( // (2,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B1 where T : A1 { } // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(2, 30), // (2,29): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class B1 where T : A1 { } // 1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(2, 29), // (3,27): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B2 where T : A2 { } // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 27), // (3,26): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // class B2 where T : A2 { } // 2 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(3, 26), // (5,10): warning CS8634: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'A1'. Nullability of type argument 'T?' doesn't match 'class' constraint. // class B3 where T : A1 { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "T").WithArguments("A1", "U", "T?").WithLocation(5, 10), // (5,10): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'A1'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // class B3 where T : A1 { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "T").WithArguments("A1", "T", "U", "T?").WithLocation(5, 10), // (7,10): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'A2'. Nullability of type argument 'T?' doesn't match 'class' constraint. // class B4 where T : A2 { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "T").WithArguments("A2", "T", "T?").WithLocation(7, 10)); } // Boxing conversion. [Fact] public void Constraint_BoxingConversion() { var source0 = @"public interface I { } public interface IIn { } public interface IOut { } public struct S0 : I { } public struct SIn0 : IIn { } public struct SOut0 : IOut { } public class A { public static void F0() where T : I { } public static void FIn0() where T : IIn { } public static void FOut0() where T : IOut { } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"struct S1 : I { } struct S2 : I { } struct SIn1 : IIn { } struct SIn2 : IIn { } struct SOut1 : IOut { } struct SOut2 : IOut { } class B : A { static void F1() where T : I { } static void F2() where T : I { } static void FIn1() where T : IIn { } static void FIn2() where T : IIn { } static void FOut1() where T : IOut { } static void FOut2() where T : IOut { } static void F() { F0(); F0(); F0(); F1(); F1(); F1(); // 1 F2(); F2(); // 2 F2(); } static void FIn() { FIn0(); FIn0(); FIn0(); FIn1(); FIn1(); FIn1(); // 3 FIn2(); FIn2(); FIn2(); } static void FOut() { FOut0(); FOut0(); FOut0(); FOut1(); FOut1(); FOut1(); FOut2(); FOut2(); // 4 FOut2(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (22,9): warning CS8627: The type 'S2' cannot be used as type parameter 'T' in the generic type or method 'B.F1()'. Nullability of type argument 'S2' doesn't match constraint type 'I'. // F1(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F1").WithArguments("B.F1()", "I", "T", "S2").WithLocation(22, 9), // (24,9): warning CS8627: The type 'S1' cannot be used as type parameter 'T' in the generic type or method 'B.F2()'. Nullability of type argument 'S1' doesn't match constraint type 'I'. // F2(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F2").WithArguments("B.F2()", "I", "T", "S1").WithLocation(24, 9), // (34,9): warning CS8627: The type 'SIn2' cannot be used as type parameter 'T' in the generic type or method 'B.FIn1()'. Nullability of type argument 'SIn2' doesn't match constraint type 'IIn'. // FIn1(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "FIn1").WithArguments("B.FIn1()", "IIn", "T", "SIn2").WithLocation(34, 9), // (48,9): warning CS8627: The type 'SOut1' cannot be used as type parameter 'T' in the generic type or method 'B.FOut2()'. Nullability of type argument 'SOut1' doesn't match constraint type 'IOut'. // FOut2(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "FOut2").WithArguments("B.FOut2()", "IOut", "T", "SOut1").WithLocation(48, 9)); } [Fact] public void Constraint_ImplicitTypeParameterConversion() { var source0 = @"public interface I { } public interface IIn { } public interface IOut { } public class A { public static void F0() where T : I { } public static void FIn0() where T : IIn { } public static void FOut0() where T : IOut { } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class B : A { static void F1() where T : I { } static void F2() where T : I { } static void FIn1() where T : IIn { } static void FIn2() where T : IIn { } static void FOut1() where T : IOut { } static void FOut2() where T : IOut { } static void F() where T : I where U : I { F0(); F0(); F1(); F1(); // 1 F2(); // 2 F2(); } static void FIn() where T : IIn where U : IIn { FIn0(); FIn0(); FIn1(); FIn1(); // 3 FIn2(); FIn2(); } static void FOut() where T : IOut where U : IOut { FOut0(); FOut0(); FOut1(); FOut1(); FOut2(); // 4 FOut2(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (14,9): warning CS8627: The type 'U' cannot be used as type parameter 'T' in the generic type or method 'B.F1()'. Nullability of type argument 'U' doesn't match constraint type 'I'. // F1(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F1").WithArguments("B.F1()", "I", "T", "U").WithLocation(14, 9), // (15,9): warning CS8627: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'B.F2()'. Nullability of type argument 'T' doesn't match constraint type 'I'. // F2(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F2").WithArguments("B.F2()", "I", "T", "T").WithLocation(15, 9), // (23,9): warning CS8627: The type 'U' cannot be used as type parameter 'T' in the generic type or method 'B.FIn1()'. Nullability of type argument 'U' doesn't match constraint type 'IIn'. // FIn1(); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "FIn1").WithArguments("B.FIn1()", "IIn", "T", "U").WithLocation(23, 9), // (33,9): warning CS8627: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'B.FOut2()'. Nullability of type argument 'T' doesn't match constraint type 'IOut'. // FOut2(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "FOut2").WithArguments("B.FOut2()", "IOut", "T", "T").WithLocation(33, 9)); } [Fact] public void Constraint_MethodTypeInference() { var source0 = @"public class A { } public class B { public static void F0(T t) where T : A { } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); comp0.VerifyDiagnostics(); var ref0 = comp0.EmitToImageReference(); var source = @"class C : B { static void F1(T t) where T : A { } static void G(A x, A? y) { F0(x); F1(x); F0(y); F1(y); // 1 x = y; F0(x); F1(x); // 2 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); comp.VerifyDiagnostics( // (11,9): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C.F1(T)'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // F1(y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F1").WithArguments("C.F1(T)", "A", "T", "A?").WithLocation(11, 9), // (12,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = y; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(12, 13), // (14,9): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'C.F1(T)'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // F1(x); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F1").WithArguments("C.F1(T)", "A", "T", "A?").WithLocation(14, 9)); } [Fact] [WorkItem(29999, "https://github.com/dotnet/roslyn/issues/29999")] public void ThisAndBaseMemberInLambda() { var source = @"delegate void D(); class A { internal string? F; } class B : A { void M() { D d; d = () => { int n = this.F.Length; // 1 this.F = string.Empty; n = this.F.Length; }; d = () => { int n = base.F.Length; // 2 base.F = string.Empty; n = base.F.Length; }; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,21): warning CS8602: Dereference of a possibly null reference. // int n = this.F.Length; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "this.F").WithLocation(13, 21), // (19,21): warning CS8602: Dereference of a possibly null reference. // int n = base.F.Length; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "base.F").WithLocation(19, 21)); } [Fact] [WorkItem(29999, "https://github.com/dotnet/roslyn/issues/29999")] public void ThisAndBaseMemberInLocalFunction() { var source = @"#pragma warning disable 8321 class A { internal string? F; } class B : A { void M() { void f() { int n = this.F.Length; // 1 this.F = string.Empty; n = this.F.Length; } void g() { int n = base.F.Length; // 2 base.F = string.Empty; n = base.F.Length; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,21): warning CS8602: Dereference of a possibly null reference. // int n = this.F.Length; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "this.F").WithLocation(12, 21), // (18,21): warning CS8602: Dereference of a possibly null reference. // int n = base.F.Length; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "base.F").WithLocation(18, 21)); } [WorkItem(31620, "https://github.com/dotnet/roslyn/issues/31620")] [Fact] public void InstanceMemberInLambda() { var source = @"using System; class Program { private object? _f; private object _g = null!; private void F() { Func f = (bool b1) => { Func g = (bool b2) => { if (b2) { _g = null; // 1 return _g; // 2 } return _g; }; if (b1) return _f; // 3 _f = new object(); return _f; }; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,26): warning CS8625: Cannot convert null literal to non-nullable reference type. // _g = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 26), // (15,28): warning CS8603: Possible null reference return. // return _g; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "_g").WithLocation(15, 28), // (19,28): warning CS8603: Possible null reference return. // if (b1) return _f; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "_f").WithLocation(19, 28)); } [WorkItem(31620, "https://github.com/dotnet/roslyn/issues/31620")] [Fact] public void InstanceMemberInLocalFunction() { var source = @"#pragma warning disable 8321 class Program { private object? _f; private object _g = null!; private void F() { object f(bool b1) { if (b1) return _f; // 1 _f = new object(); return _f; object g(bool b2) { if (b2) { _g = null; // 2 return _g; // 3 } return _g; } } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,28): warning CS8603: Possible null reference return. // if (b1) return _f; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "_f").WithLocation(10, 28), // (17,26): warning CS8625: Cannot convert null literal to non-nullable reference type. // _g = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(17, 26), // (18,28): warning CS8603: Possible null reference return. // return _g; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "_g").WithLocation(18, 28)); } [WorkItem(29049, "https://github.com/dotnet/roslyn/issues/29049")] [Fact] public void TypeWithAnnotations_GetHashCode() { var source = @"interface I { } class A : I { } class B where T : I { } class Program { static void Main() { new B(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,15): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B'. Nullability of type argument 'A' doesn't match constraint type 'I'. // new B(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B", "I", "T", "A").WithLocation(8, 15)); // Diagnostics must support GetHashCode() and Equals(), to allow removing // duplicates (see CommonCompiler.ReportErrors). foreach (var diagnostic in diagnostics) { diagnostic.GetHashCode(); Assert.True(diagnostic.Equals(diagnostic)); } } [WorkItem(29041, "https://github.com/dotnet/roslyn/issues/29041")] [WorkItem(29048, "https://github.com/dotnet/roslyn/issues/29048")] [WorkItem(30001, "https://github.com/dotnet/roslyn/issues/30001")] [Fact] public void ConstraintCyclesFromMetadata_01() { var source0 = @"using System; public class A0 where T : IEquatable { } public class A1 where T : class, IEquatable { } public class A3 where T : struct, IEquatable { } public class A4 where T : struct, IEquatable { } public class A5 where T : IEquatable { } public class A6 where T : IEquatable { }"; var source = @"class B { static void Main() { new A0(); // 1 new A0(); new A5(); // 4 new A5(); // 5 } }"; // No [NullNullTypes] var comp0 = CreateCompilation(source0); var ref0 = comp0.EmitToImageReference(); var comp = CreateCompilation(source, references: new[] { ref0 }); var expectedDiagnostics = new[] { // (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A0(); // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22), // (9,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A5(); // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 22) }; comp.VerifyDiagnostics(expectedDiagnostics); verifyTypeParameterConstraint("A0", "System.IEquatable"); verifyTypeParameterConstraint("A1", "System.IEquatable"); verifyTypeParameterConstraint("A3", "System.IEquatable"); verifyTypeParameterConstraint("A4", "System.IEquatable"); verifyTypeParameterConstraint("A5", "System.IEquatable"); verifyTypeParameterConstraint("A6", "System.IEquatable"); // [NullNullTypes(false)] comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesFalse()); ref0 = comp0.EmitToImageReference(); comp = CreateCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics(expectedDiagnostics); verifyTypeParameterConstraint("A0", "System.IEquatable"); verifyTypeParameterConstraint("A1", "System.IEquatable"); verifyTypeParameterConstraint("A3", "System.IEquatable"); verifyTypeParameterConstraint("A4", "System.IEquatable"); verifyTypeParameterConstraint("A5", "System.IEquatable"); verifyTypeParameterConstraint("A6", "System.IEquatable"); // [NullNullTypes(true)] comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); ref0 = comp0.EmitToImageReference(); comp = CreateCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A0(); // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22), // (9,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A5(); // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 22) ); verifyTypeParameterConstraint("A0", "System.IEquatable"); verifyTypeParameterConstraint("A1", "System.IEquatable"); verifyTypeParameterConstraint("A3", "System.IEquatable"); verifyTypeParameterConstraint("A4", "System.IEquatable"); verifyTypeParameterConstraint("A5", "System.IEquatable"); verifyTypeParameterConstraint("A6", "System.IEquatable"); comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,16): warning CS8631: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A0'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable'. // new A0(); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A0", "System.IEquatable", "T", "string?").WithLocation(5, 16), // (9,16): warning CS8631: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A5'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable'. // new A5(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A5", "System.IEquatable", "T", "string?").WithLocation(9, 16) ); verifyTypeParameterConstraint("A0", "System.IEquatable"); verifyTypeParameterConstraint("A1", "System.IEquatable"); verifyTypeParameterConstraint("A3", "System.IEquatable"); verifyTypeParameterConstraint("A4", "System.IEquatable"); verifyTypeParameterConstraint("A5", "System.IEquatable"); verifyTypeParameterConstraint("A6", "System.IEquatable"); void verifyTypeParameterConstraint(string typeName, string expected) { var type = comp.GetMember(typeName); var constraintType = type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0]; Assert.Equal(expected, constraintType.ToTestDisplayString()); } } [WorkItem(29041, "https://github.com/dotnet/roslyn/issues/29041")] [WorkItem(29048, "https://github.com/dotnet/roslyn/issues/29048")] [WorkItem(30003, "https://github.com/dotnet/roslyn/issues/30003")] [Fact] public void ConstraintCyclesFromMetadata_02() { var source0 = @"using System; public class A2 where T : class, IEquatable { } "; var source = @"class B { static void Main() { new A2(); // 2 new A2(); // 3 } }"; // No [NullNullTypes] var comp0 = CreateCompilation(source0); comp0.VerifyDiagnostics( // (2,48): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public class A2 where T : class, IEquatable { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(2, 48), // (2,49): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public class A2 where T : class, IEquatable { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(2, 49) ); MetadataReference ref0 = comp0.ToMetadataReference(); var comp = CreateCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A2(); // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22) ); verifyTypeParameterConstraint("A2", "System.IEquatable"); // [NullNullTypes(false)] comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesFalse()); comp0.VerifyDiagnostics( // (2,48): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public class A2 where T : class, IEquatable { } Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(2, 48), // (2,49): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // public class A2 where T : class, IEquatable { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(2, 49) ); ref0 = comp0.ToMetadataReference(); comp = CreateCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A2(); // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22) ); verifyTypeParameterConstraint("A2", "System.IEquatable"); // [NullNullTypes(true)] comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); ref0 = comp0.EmitToImageReference(); comp = CreateCompilation(source, references: new[] { ref0 }); comp.VerifyDiagnostics( // (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // new A2(); // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22) ); verifyTypeParameterConstraint("A2", "System.IEquatable"); comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,16): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A2'. Nullability of type argument 'string?' doesn't match 'class' constraint. // new A2(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("A2", "T", "string?").WithLocation(5, 16), // (5,16): warning CS8631: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A2'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable'. // new A2(); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A2", "System.IEquatable", "T", "string?").WithLocation(5, 16) ); verifyTypeParameterConstraint("A2", "System.IEquatable"); void verifyTypeParameterConstraint(string typeName, string expected) { var type = comp.GetMember(typeName); var constraintType = type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0]; Assert.Equal(expected, constraintType.ToTestDisplayString()); } } [WorkItem(29186, "https://github.com/dotnet/roslyn/issues/29186")] [Fact] public void AttributeArgumentCycle_OtherAttribute() { var source = @"using System; class AAttribute : Attribute { internal AAttribute(object o) { } } interface IA { } interface IB where T : IA { } [A(typeof(IB))] class C { }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(30178, "https://github.com/dotnet/roslyn/issues/30178")] public void GenericSubstitution_01() { var source = @" #nullable enable class A where T1 : class where T2 : class { T1 F; #nullable disable class B : A { #nullable enable void M1() { F = null; // 1 } } void M2() { F = null; // 2 } #nullable disable class C : A { #nullable enable void M3() { F = null; // 3 } } #nullable disable class D : A { #nullable enable void M4() { F = null; // 4 } } #nullable disable class E : A { #nullable enable void M5() { F = null; // 5 } } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (7,8): warning CS8618: Non-nullable field 'F' is uninitialized. // T1 F; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(7, 8), // (7,8): warning CS0414: The field 'A.F' is assigned but its value is never used // T1 F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("A.F").WithLocation(7, 8), // (15,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(15, 17), // (21,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(21, 13), // (30,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(30, 17), // (40,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(40, 17), // (50,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(50, 17) ); var b = comp.GetTypeByMetadataName("A`2+B"); Assert.NotNull(b); Assert.True(b.BaseTypeNoUseSiteDiagnostics.IsDefinition); } [Fact] [WorkItem(30177, "https://github.com/dotnet/roslyn/issues/30177")] [WorkItem(30178, "https://github.com/dotnet/roslyn/issues/30178")] public void GenericSubstitution_02() { var source = @" #nullable disable class A where T1 : class where T2 : class { #nullable enable #pragma warning disable 8618 T1 F; #nullable enable class B : A { void M1() { F = null; // 1 } } #nullable enable void M2() { F = null; // 2 } #nullable enable class C : A { void M3() { F = null; // 3 } } #nullable enable class D : A { void M4() { F = null; // 4 } } #nullable enable class E : A { void M5() { F = null; // 5 } } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (9,8): warning CS0414: The field 'A.F' is assigned but its value is never used // T1 F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("A.F").WithLocation(9, 8), // (16,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 1 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(16, 17), // (23,13): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 2 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(23, 13), // (31,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(31, 17), // (40,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 4 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(40, 17), // (49,17): warning CS8654: A null literal introduces a null value when 'T2' is a non-nullable reference type. // F = null; // 5 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T2").WithLocation(49, 17)); var b = comp.GetTypeByMetadataName("A`2+B"); Assert.NotNull(b); Assert.False(b.BaseTypeNoUseSiteDiagnostics.IsDefinition); } [Fact] public void GenericSubstitution_03() { var source = @"#nullable disable class A where T : class { class B : A {} } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); var b = comp.GetTypeByMetadataName("A`1+B"); Assert.NotNull(b); Assert.True(b.BaseTypeNoUseSiteDiagnostics.IsDefinition); } [Fact] [WorkItem(30178, "https://github.com/dotnet/roslyn/issues/30178")] public void GenericSubstitution_04() { var source = @"#nullable enable class A where T : class { class B : A {} } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); var b = comp.GetTypeByMetadataName("A`1+B"); Assert.NotNull(b); Assert.False(b.BaseTypeNoUseSiteDiagnostics.IsDefinition); } [Fact] [WorkItem(30178, "https://github.com/dotnet/roslyn/issues/30178")] public void GenericSubstitution_05() { var source = @" #nullable enable class A where T1 : class where T2 : class { #nullable disable T1 F; #nullable enable class B : A { void M1() { F = null; // 1 } } void M2() { F = null; // 2 } class C : A { void M3() { F = null; // 3 } } class D : A { void M1() { F = null; // 4 } } class E : A { void M1() { F = null; // 5 } } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (8,8): warning CS0414: The field 'A.F' is assigned but its value is never used // T1 F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("A.F").WithLocation(8, 8), // (14,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 17), // (27,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(27, 17), // (35,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 4 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(35, 17), // (43,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(43, 17) ); var b = comp.GetTypeByMetadataName("A`2+B"); Assert.NotNull(b); Assert.False(b.BaseTypeNoUseSiteDiagnostics.IsDefinition); } [Fact] [WorkItem(30177, "https://github.com/dotnet/roslyn/issues/30177")] [WorkItem(30178, "https://github.com/dotnet/roslyn/issues/30178")] public void GenericSubstitution_06() { var source = @" #nullable disable class A where T1 : class where T2 : class { T1 F; #nullable enable class B : A { void M1() { F = null; // 1 } } #nullable enable void M2() { F = null; } #nullable enable class C : A { void M3() { F = null; // 2 } } #nullable enable class D : A { void M3() { F = null; // 3 } } #nullable enable class E : A { void M3() { F = null; // 4 } } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (7,8): warning CS0414: The field 'A.F' is assigned but its value is never used // T1 F; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F").WithArguments("A.F").WithLocation(7, 8), // (14,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 1 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(14, 17), // (29,17): warning CS8625: Cannot convert null literal to non-nullable reference type. // F = null; // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(29, 17), // (38,17): warning CS8654: A null literal introduces a null value when 'T1' is a non-nullable reference type. // F = null; // 3 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T1").WithLocation(38, 17), // (47,17): warning CS8654: A null literal introduces a null value when 'T2' is a non-nullable reference type. // F = null; // 4 Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T2").WithLocation(47, 17)); var b = comp.GetTypeByMetadataName("A`2+B"); Assert.NotNull(b); Assert.False(b.BaseTypeNoUseSiteDiagnostics.IsDefinition); } [Fact] [WorkItem(35083, "https://github.com/dotnet/roslyn/issues/35083")] public void GenericSubstitution_07() { var source = @" class A { void M1() { } } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics(); var a = comp.GetTypeByMetadataName("A"); var m1 = a.GetMember("M1"); var m11 = new[] { m1.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(a, NullableAnnotation.Annotated))), m1.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(a, NullableAnnotation.NotAnnotated))), m1.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(a, NullableAnnotation.Oblivious))) }; var m12 = new[] { m1.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(a, NullableAnnotation.Annotated))), m1.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(a, NullableAnnotation.NotAnnotated))), m1.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(a, NullableAnnotation.Oblivious))) }; for (int i = 0; i < m11.Length; i++) { var method1 = m11[i]; Assert.True(method1.Equals(method1)); for (int j = 0; j < m12.Length; j++) { var method2 = m12[j]; if (i == j) { Assert.True(method1.Equals(method2)); Assert.True(method2.Equals(method1)); } else { Assert.False(method1.Equals(method2)); Assert.False(method2.Equals(method1)); } Assert.Equal(method1.GetHashCode(), method2.GetHashCode()); } } } [Fact] [WorkItem(30171, "https://github.com/dotnet/roslyn/issues/30171")] public void NonNullTypesContext_01() { var source = @" using System.Diagnostics.CodeAnalysis; class A { #nullable disable PLACEHOLDER B[] F1; #nullable enable PLACEHOLDER C[] F2; } class B {} class C {} "; var comp1 = CreateCompilation(new[] { source.Replace("PLACEHOLDER", "") }); verify(comp1); var comp2 = CreateCompilation(new[] { source.Replace("PLACEHOLDER", "annotations") }); verify(comp2); void verify(Compilation comp) { var f1 = comp.GetMember("A.F1"); Assert.Equal("B[]", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); var f2 = comp.GetMember("A.F2"); Assert.Equal("C![]!", f2.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var arrays = tree.GetRoot().DescendantNodes().OfType().ToArray(); Assert.Equal(2, arrays.Length); Assert.Equal("B[]", model.GetTypeInfo(arrays[0]).Type.ToTestDisplayString(includeNonNullable: true)); Assert.Equal("C![]", model.GetTypeInfo(arrays[1]).Type.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_02() { var source0 = @" #pragma warning disable CS0169 class A { #nullable enable PLACEHOLDER B #nullable disable PLACEHOLDER F1; } class B {} "; var source1 = source0.Replace("PLACEHOLDER", ""); var source2 = source0.Replace("PLACEHOLDER", "annotations"); assertNonNullTypesContext(source1, NullableContextOptions.Disable); assertNonNullTypesContext(source1, NullableContextOptions.Warnings); assertNonNullTypesContext(source2, NullableContextOptions.Disable); assertNonNullTypesContext(source2, NullableContextOptions.Warnings); void assertNonNullTypesContext(string source, NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_03() { var source = @" #pragma warning disable CS0169 class A { #nullable disable PLACEHOLDER B #nullable enable PLACEHOLDER F1; } class B {} "; verify(source.Replace("PLACEHOLDER", "")); verify(source.Replace("PLACEHOLDER", "annotations")); void verify(string source) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_04() { var source0 = @" #pragma warning disable CS0169 class A { B #nullable enable PLACEHOLDER ? F1; } class B {} "; var source1 = source0.Replace("PLACEHOLDER", ""); var source2 = source0.Replace("PLACEHOLDER", "annotations"); assertNonNullTypesContext(source1, NullableContextOptions.Disable); assertNonNullTypesContext(source1, NullableContextOptions.Warnings); assertNonNullTypesContext(source2, NullableContextOptions.Disable); assertNonNullTypesContext(source2, NullableContextOptions.Warnings); void assertNonNullTypesContext(string source, NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_05() { var source = @" #pragma warning disable CS0169 class A { B #nullable disable PLACEHOLDER ? F1; } class B {} "; verify(source.Replace("PLACEHOLDER", "")); verify(source.Replace("PLACEHOLDER", "annotations")); void verify(string source) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics( // (8,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // ? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 6) ); } } [Fact] public void NonNullTypesContext_06() { var source0 = @" #pragma warning disable CS0169 class A { #nullable enable PLACEHOLDER string #nullable disable PLACEHOLDER F1; } "; var source1 = source0.Replace("PLACEHOLDER", ""); var source2 = source0.Replace("PLACEHOLDER", "annotations"); assertNonNullTypesContext(source1, NullableContextOptions.Disable); assertNonNullTypesContext(source1, NullableContextOptions.Warnings); assertNonNullTypesContext(source2, NullableContextOptions.Disable); assertNonNullTypesContext(source2, NullableContextOptions.Warnings); void assertNonNullTypesContext(string source, NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("System.String!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_07() { var source = @" #pragma warning disable CS0169 class A { #nullable disable string #nullable enable F1; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("System.String", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_08() { var source = @" #pragma warning disable CS0169 class A { B[ #nullable enable ] #nullable disable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B[]!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_09() { var source = @" #pragma warning disable CS0169 class A { B[ #nullable disable ] #nullable enable F1; } class B {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("B![]", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_10() { var source = @" #pragma warning disable CS0169 class A { (B, B #nullable enable ) #nullable disable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal(NullableAnnotation.NotAnnotated, f1.TypeWithAnnotations.NullableAnnotation); } } [Fact] public void NonNullTypesContext_11() { var source = @" #pragma warning disable CS0169 class A { (B, B #nullable disable ) #nullable enable F1; } class B {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal(NullableAnnotation.Oblivious, f1.TypeWithAnnotations.NullableAnnotation); } [Fact] public void NonNullTypesContext_12() { var source = @" #pragma warning disable CS0169 class A { B #nullable disable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_13() { var source = @" #pragma warning disable CS0169 class A { B #nullable enable F1; } class B {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_14() { var source = @" class A { void M(out T x){} void Test() { M(out #nullable enable var #nullable disable local); } } class var {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var decl = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("var!", ((LocalSymbol)model.GetDeclaredSymbol(decl.Designation)).TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_15() { var source = @" class A { void M(out T x){} void Test() { M(out #nullable disable var #nullable enable local); } } class var {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var decl = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("var", ((LocalSymbol)model.GetDeclaredSymbol(decl.Designation)).TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_16() { var source = @" class A where T : #nullable enable class #nullable disable { } "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var a = comp.GetTypeByMetadataName("A`1"); Assert.Equal("A where T : class!", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); } } [Fact] public void NonNullTypesContext_17() { var source = @" class A where T : #nullable disable class #nullable enable { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var a = comp.GetTypeByMetadataName("A`1"); Assert.Equal("A where T : class", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); } [Fact] public void NonNullTypesContext_18() { var source = @" class A where T : class #nullable enable ? #nullable disable { } "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var a = comp.GetTypeByMetadataName("A`1"); Assert.Equal("A where T : class?", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_19() { var source = @" class A where T : class #nullable disable ? #nullable enable { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var a = comp.GetTypeByMetadataName("A`1"); Assert.Equal("A where T : class?", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); comp.VerifyDiagnostics( // (4,5): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // ? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 5) ); } [Fact] public void NonNullTypesContext_20() { var source = @" class A where T : #nullable enable unmanaged #nullable disable { } class unmanaged {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var a = comp.GetTypeByMetadataName("A`1"); Assert.Equal("A where T : unmanaged!", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); } } [Fact] public void NonNullTypesContext_21() { var source = @" class A where T : #nullable disable unmanaged #nullable enable { } class unmanaged {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var a = comp.GetTypeByMetadataName("A`1"); Assert.Equal("A where T : unmanaged", a.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier))); } [Fact] public void NonNullTypesContext_22() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Enable, type, "A"); } private static void AssertGetSpeculativeTypeInfo(string source, NullableContextOptions nullableContextOptions, TypeSyntax type, string expected) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var decl = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal(expected, model.GetSpeculativeTypeInfo(decl.Identifier.SpanStart, type, SpeculativeBindingOption.BindAsTypeOrNamespace).Type.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_23() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Disable, type, "A"); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_24() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable disable A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Enable, type, "A"); } [Fact] public void NonNullTypesContext_25() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable enable A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Disable, type, "A"); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_26() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable disable b; #nullable enable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Enable, type, "A"); } [Fact] public void NonNullTypesContext_27() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable enable b; #nullable disable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Disable, type, "A"); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_28() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable disable b; #nullable enable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable enable A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Enable, type, "A"); } [Fact] public void NonNullTypesContext_29() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable enable b; #nullable disable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable disable A " ); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Disable, type, "A"); AssertGetSpeculativeTypeInfo(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_30() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A"); } private static void AssertTryGetSpeculativeSemanticModel(string source, NullableContextOptions nullableContextOptions, TypeSyntax type, string expected) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var decl = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.True(model.TryGetSpeculativeSemanticModel(decl.Identifier.SpanStart, type, out model, SpeculativeBindingOption.BindAsTypeOrNamespace)); Assert.Equal(expected, model.GetTypeInfo(type).Type.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_31() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A"); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_32() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable disable A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A"); } [Fact] public void NonNullTypesContext_33() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string b; } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable enable A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A"); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_34() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable disable b; #nullable enable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A"); } [Fact] public void NonNullTypesContext_35() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable enable b; #nullable disable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A"); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_36() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable disable b; #nullable enable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable enable A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A"); } [Fact] public void NonNullTypesContext_37() { var source = @" #pragma warning disable CS0169 class A { void Tests() { string #nullable enable b; #nullable disable } } "; TypeSyntax type = SyntaxFactory.ParseTypeName( @" #nullable disable A " ); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A"); AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A"); } [Fact] public void NonNullTypesContext_38() { var source = @" using B = C; #pragma warning disable CS0169 class A { #nullable enable B #nullable disable F1; } class C {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("C!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_39() { var source = @" using B = C; #pragma warning disable CS0169 class A { #nullable disable B #nullable enable F1; } class C {} "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("C", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_40() { var source = @" #pragma warning disable CS0169 class A { C. #nullable enable B #nullable disable F1; } namespace C { class B {} } "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("C.B!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_41() { var source = @" #pragma warning disable CS0169 class A { C. #nullable disable B #nullable enable F1; } namespace C { class B {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("C.B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_42() { var source = @" #pragma warning disable CS0169 class A { C.B #nullable disable F1; } namespace C { class B {} } "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("C.B!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } } [Fact] public void NonNullTypesContext_43() { var source = @" #pragma warning disable CS0169 class A { C.B #nullable enable F1; } namespace C { class B {} } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); var f1 = comp.GetMember("A.F1"); Assert.Equal("C.B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); } [Fact] public void NonNullTypesContext_49() { var source = @" #pragma warning disable CS0169 #nullable enable class A { B #nullable restore ? #nullable enable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics( // (8,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // ? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 6) ); } } [Fact] public void NonNullTypesContext_51() { var source = @" #pragma warning disable CS0169 class A { B #nullable restore ? F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics( // (8,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // ? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 6) ); } } [Fact] public void NonNullTypesContext_52() { var source = @" #pragma warning disable CS0169 #nullable disable class A { B #nullable restore ? #nullable enable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics( // (8,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // ? Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 6) ); } } [Fact] public void NonNullTypesContext_53() { var source = @" #pragma warning disable CS0169 #nullable enable class A { #nullable restore B #nullable enable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_55() { var source = @" #pragma warning disable CS0169 class A { #nullable restore B F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_56() { var source = @" #pragma warning disable CS0169 #nullable disable class A { #nullable restore B #nullable enable F1; } class B {} "; assertNonNullTypesContext(NullableContextOptions.Disable); assertNonNullTypesContext(NullableContextOptions.Warnings); void assertNonNullTypesContext(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source }, options: compilationOptions); var f1 = comp.GetMember("A.F1"); Assert.Equal("B", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_57() { var source = @" #pragma warning disable CS0169 #nullable disable class A { B #nullable restore ? #nullable disable F1; } class B {} "; assertType(NullableContextOptions.Enable); void assertType(NullableContextOptions nullableContextOptions) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_58() { var source = @" #pragma warning disable CS0169 #nullable disable class A { B #nullable restore ? #nullable disable F1; } class B {} "; assertType(NullableContextOptions.Enable); void assertType(NullableContextOptions nullableContextOptions) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_59() { var source = @" #pragma warning disable CS0169 class A { B #nullable restore ? F1; } class B {} "; assertType(NullableContextOptions.Enable); void assertType(NullableContextOptions nullableContextOptions) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_60() { var source = @" #pragma warning disable CS0169 #nullable enable class A { B #nullable restore ? #nullable disable F1; } class B {} "; assertType(NullableContextOptions.Enable); void assertType(NullableContextOptions nullableContextOptions) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var f1 = comp.GetMember("A.F1"); Assert.Equal("B?", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_61() { var source = @" #pragma warning disable CS0169 #nullable disable class A { #nullable restore B #nullable disable F1; } class B {} "; assertType(NullableContextOptions.Enable); void assertType(NullableContextOptions nullableContextOptions) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var f1 = comp.GetMember("A.F1"); Assert.Equal("B!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] public void NonNullTypesContext_62() { var source = @" #pragma warning disable CS0169 class A { #nullable restore #pragma warning disable CS8618 B F1; } class B {} "; assertType(NullableContextOptions.Enable); void assertType(NullableContextOptions nullableContextOptions) { var comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(nullableContextOptions)); var f1 = comp.GetMember("A.F1"); Assert.Equal("B!", f1.TypeWithAnnotations.ToTestDisplayString(includeNonNullable: true)); comp.VerifyDiagnostics(); } } [Fact] [WorkItem(34843, "https://github.com/dotnet/roslyn/issues/34843")] [WorkItem(34844, "https://github.com/dotnet/roslyn/issues/34844")] public void ObliviousTypeParameter_01() { var source = $@" #pragma warning disable {(int)ErrorCode.WRN_UninitializedNonNullableField} #pragma warning disable {(int)ErrorCode.WRN_UnreferencedField} #pragma warning disable {(int)ErrorCode.WRN_UnreferencedFieldAssg} #pragma warning disable {(int)ErrorCode.WRN_UnreferencedVarAssg} #pragma warning disable {(int)ErrorCode.WRN_UnassignedInternalField} " + @" #nullable disable class A where T2 : class where T3 : B { T1 F1; T2 F2; T3 F3; B F4; #nullable enable void M1() { F1.ToString(); F2.ToString(); F3.ToString(); F4.ToString(); } #nullable enable void M2() { T1 x2 = default; T2 y2 = default; T3 z2 = default; } #nullable enable void M3() { C.Test(); C.Test(); C.Test(); } #nullable enable void M4() { D.Test(F1); D.Test(F2); D.Test(F3); D.Test(F4); } } class B {} #nullable enable class C { public static void Test() where T : notnull {} } #nullable enable class D { public static void Test(T x) where T : notnull {} } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (29,17): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // T1 x2 = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(29, 17), // (30,17): warning CS8653: A default expression introduces a null value when 'T2' is a non-nullable reference type. // T2 y2 = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T2").WithLocation(30, 17), // (31,17): warning CS8653: A default expression introduces a null value when 'T3' is a non-nullable reference type. // T3 z2 = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T3").WithLocation(31, 17) ); } [Fact] [WorkItem(30220, "https://github.com/dotnet/roslyn/issues/30220")] public void ObliviousTypeParameter_02() { var source = $@" #pragma warning disable {(int)ErrorCode.WRN_UnreferencedVar} " + @" #nullable enable class A where T1 : class { #nullable disable class B where T2 : T1 { } #nullable enable void M1() { B a1; B b1; A.B c1; A.B d1; A.B e1; A.B f1; } } class C {} "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( // (20,17): warning CS8631: The type 'T1?' cannot be used as type parameter 'T2' in the generic type or method 'A.B'. Nullability of type argument 'T1?' doesn't match constraint type 'T1'. // A.B d1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "T1?").WithArguments("A.B", "T1", "T2", "T1?").WithLocation(20, 17), // (22,16): warning CS8631: The type 'C?' cannot be used as type parameter 'T2' in the generic type or method 'A.B'. Nullability of type argument 'C?' doesn't match constraint type 'C'. // A.B f1; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "C?").WithArguments("A.B", "C", "T2", "C?").WithLocation(22, 16) ); } [Fact] [WorkItem(34842, "https://github.com/dotnet/roslyn/issues/34842")] public void ObliviousTypeParameter_03() { var source = $@"#pragma warning disable {(int)ErrorCode.WRN_UnreferencedFieldAssg} " + @"#nullable disable class A where T2 : class where T3 : notnull { T1 F1; T2 F2; T3 F3; B F4; #nullable enable void M1() { F1 = default; F2 = default; F2 = null; F3 = default; F4 = default; } } class B { } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( ); } [Fact] [WorkItem(34842, "https://github.com/dotnet/roslyn/issues/34842")] public void ObliviousTypeParameter_04() { var source = @"#nullable disable class A where T2 : class where T3 : notnull { void M1(T1 x, T2 y, T3 z, B w) #nullable enable { x = default; y = default; y = null; z = default; w = default; } } class B { } "; var comp = CreateCompilation(new[] { source }); comp.VerifyDiagnostics( ); } [WorkItem(23270, "https://github.com/dotnet/roslyn/issues/23270")] [Fact] public void NotNullAfterDereference_00() { var source = @"class Program { static void M(object? obj) { obj.F(); obj.ToString(); // 1 obj.ToString(); } } static class E { internal static void F(this object? obj) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // obj.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "obj").WithLocation(6, 9)); } [WorkItem(23270, "https://github.com/dotnet/roslyn/issues/23270")] [Fact] public void NotNullAfterDereference_01() { var source = @"class Program { static void F(object? x) { x.ToString(); // 1 object? y; y.ToString(); y = null; y.ToString(); // 2 x.ToString(); y.ToString(); x = y; if (y != null) { x.ToString(); } x.ToString(); y.ToString(); // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(5, 9), // (7,9): error CS0165: Use of unassigned local variable 'y' // y.ToString(); Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(7, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(18, 9) ); } [Fact] public void NotNullAfterDereference_02() { var source = @"class Program { static void F(T x) { x.ToString(); // 1 T y; y.ToString(); y = default; y.ToString(); // 2 x.ToString(); y.ToString(); x = y; if (y != null) { x.ToString(); } x.ToString(); y.ToString(); // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(5, 9), // (7,9): error CS0165: Use of unassigned local variable 'y' // y.ToString(); Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(7, 9), // (8,13): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // y = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(8, 13), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(18, 9) ); } [Fact] public void NotNullAfterDereference_03() { var source = @"class C { void F1(C x) { } static void G1(C? x) { x?.F1(x); x!.F1(x); x.F1(x); } static void G2(C? y) { y?.F2(y); y!.F2(y); // 3 y.F2(y); // 4, 5 } } static class E { internal static void F2(this C x, C y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,15): warning CS8604: Possible null reference argument for parameter 'y' in 'void E.F2(C x, C y)'. // y!.F2(y); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("y", "void E.F2(C x, C y)").WithLocation(13, 15), // (14,9): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F2(C x, C y)'. // y.F2(y); // 4, 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F2(C x, C y)").WithLocation(14, 9), // (14,14): warning CS8604: Possible null reference argument for parameter 'y' in 'void E.F2(C x, C y)'. // y.F2(y); // 4, 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("y", "void E.F2(C x, C y)").WithLocation(14, 14)); } [Fact] public void NotNullAfterDereference_04() { var source = @"class Program { static void F(bool b, string? s) { int n; if (b) { n = s/*T:string?*/.Length; // 1 n = s/*T:string!*/.Length; } n = b ? s/*T:string?*/.Length + // 2 s/*T:string!*/.Length : 0; n = s/*T:string?*/.Length; // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,17): warning CS8602: Dereference of a possibly null reference. // n = s/*T:string?*/.Length; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 17), // (12,17): warning CS8602: Dereference of a possibly null reference. // n = b ? s/*T:string?*/.Length + // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(12, 17), // (14,13): warning CS8602: Dereference of a possibly null reference. // n = s/*T:string?*/.Length; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 13)); comp.VerifyTypes(); } [Fact] public void NotNullAfterDereference_05() { var source = @"class Program { static void F(string? s) { int n; try { n = s/*T:string?*/.Length; // 1 try { n = s/*T:string!*/.Length; } finally { n = s/*T:string!*/.Length; } } catch (System.IO.IOException) { n = s/*T:string?*/.Length; // 2 } catch { n = s/*T:string?*/.Length; // 3 } finally { n = s/*T:string?*/.Length; // 4 } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,17): warning CS8602: Dereference of a possibly null reference. // n = s/*T:string?*/.Length; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 17), // (20,17): warning CS8602: Dereference of a possibly null reference. // n = s/*T:string?*/.Length; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(20, 17), // (24,17): warning CS8602: Dereference of a possibly null reference. // n = s/*T:string?*/.Length; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(24, 17), // (28,17): warning CS8602: Dereference of a possibly null reference. // n = s/*T:string?*/.Length; // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(28, 17)); comp.VerifyTypes(); } [Fact] public void NotNullAfterDereference_06() { var source = @"class C { object F = default!; static void G(C? c) { c.F = c; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // One warning only, rather than one warning for dereference of c.F // and another warning for assignment c.F = c. comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // c.F = c; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(6, 9)); } [Fact] public void NotNullAfterDereference_Call() { var source = @"#pragma warning disable 0649 class C { object? y; void F(object? o) { } static void G(C? x) { x.F(x = null); // 1 x.F(x.y); // 2, 3 x.F(x.y); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for x.F(x.y). comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // x.F(x = null); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // x.F(x.y); // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(11, 9)); } [Fact] public void NotNullAfterDereference_Array() { var source = @"class Program { static int F(object? o) => 0; static void G(object[]? x, object[] y) { object z; z = x[F(x = null)]; // 1 z = x[x.Length]; // 2, 3 z = x[x.Length]; y[F(y = null)] = 1; y[y.Length] = 2; // 4, 5 y[y.Length] = 3; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for x[x.Length] and y[y.Length]. comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // z = x[F(x = null)]; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 13), // (8,13): warning CS8602: Dereference of a possibly null reference. // z = x[x.Length]; // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13), // (10,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // y[F(y = null)] = 1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 17), // (11,9): warning CS8602: Dereference of a possibly null reference. // y[y.Length] = 2; // 4, 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(11, 9)); } [Fact] public void NotNullAfterDereference_Indexer() { var source = @"#pragma warning disable 0649 class C { object? F; object this[object? o] { get { return 1; } set { } } static void G(C? x, C y) { object z; z = x[x = null]; // 1 z = x[x.F]; // 2 z = x[x.F]; y[y = null] = 1; // 3 y[y.F] = 2; // 4 y[y.F] = 3; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for x[x.F] and y[y.F]. comp.VerifyDiagnostics( // (13,13): warning CS8602: Dereference of a possibly null reference. // z = x[x = null]; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // z = x[x.F]; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(14, 13), // (16,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // y[y = null] = 1; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(16, 15), // (17,9): warning CS8602: Dereference of a possibly null reference. // y[y.F] = 2; // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(17, 9) ); } [Fact] public void NotNullAfterDereference_Field() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { object? F; static object? G(object? o) => o; static void M(C? x, C? y) { object? o; o = x.F; // 1 o = x.F; y.F = G(y = null); // 2 y.F = G(y.F); // 3, 4 y.F = G(y.F); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for y.F = G(y.F). comp.VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // o = x.F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 13), // (12,9): warning CS8602: Dereference of a possibly null reference. // y.F = G(y = null); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.F = G(y.F); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(13, 9)); } [Fact] public void NotNullAfterDereference_Property() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { object? P { get; set; } static object? F(object? o) => o; static void M(C? x, C? y) { object? o; o = x.P; // 1 o = x.P; y.P = F(y = null); // 2 y.P = F(y.P); // 3, 4 y.P = F(y.P); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for y.P = F(y.P). comp.VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // o = x.F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 13), // (12,9): warning CS8602: Dereference of a possibly null reference. // y.F = G(y = null); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.F = G(y.F); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(13, 9)); } [Fact] public void NotNullAfterDereference_Event() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 delegate void D(); class C { event D E; D F; static D G(C? c) => throw null!; static void M(C? x, C? y, C? z) { x.E(); // 1 x.E(); y.E += G(y = null); // 2 y.E += y.F; // 3, 4 y.E += y.F; y.E(); z.E = null; // 5 z.E(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for y.E += y.F. comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // x.E(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(11, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.E += G(y = null); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(13, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // y.E += y.F; // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(14, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // z.E = null; // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(17, 9), // (17,15): warning CS8625: Cannot convert null literal to non-nullable reference type. // z.E = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(17, 15), // (18,9): warning CS8602: Dereference of a possibly null reference. // z.E(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.E").WithLocation(18, 9)); } [Fact] public void NotNullAfterDereference_Dynamic() { var source = @"class Program { static void F(dynamic? d) { d.ToString(); // 1 d.ToString(); } static void G(dynamic? x, dynamic? y) { object z; z = x[x = null]; // 2 z = x[x.F]; // 3, 4 z = x[x.F]; y[y = null] = 1; y[y.F] = 2; // 5, 6 y[y.F] = 3; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/30598: Should report two warnings for x[x.F] and y[y.F]. comp.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // d.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d").WithLocation(5, 9), // (11,13): warning CS8602: Dereference of a possibly null reference. // z = x[x = null]; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(11, 13), // (12,13): warning CS8602: Dereference of a possibly null reference. // z = x[x.F]; // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(12, 13), // (14,9): warning CS8602: Dereference of a possibly null reference. // y[y = null] = 1; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(14, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // y[y.F] = 2; // 5, 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(15, 9)); } [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] [Fact] public void NotNullAfterDereference_MethodGroup_01() { var source = @"delegate void D(); class C { void F1() { } static void F(C? x, C? y) { D d; d = x.F1; // warning d = y.F2; // ok } } static class E { internal static void F2(this C? c) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // d = x.F1; // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13)); } [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] [Fact] public void NotNullAfterDereference_MethodGroup_02() { var source = @"delegate void D1(int i); delegate void D2(); class C { void F(int i) { } static void F1(D1 d) { } static void F2(D2 d) { } static void G(C? x, C? y) { F1(x.F); // 1 F1(x.F); F2(y.F); // 2 F2(y.F); // 3 } } static class E { internal static void F(this C x) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,12): warning CS8602: Dereference of a possibly null reference. // F1(x.F); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 12), // (12,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(C x)'. // F2(y.F); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(C x)").WithLocation(12, 12), // (13,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(C x)'. // F2(y.F); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(C x)").WithLocation(13, 12)); } [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] [Fact] public void MethodGroupReinferredAfterReceiver() { var source = @"public class C { G CreateG(T t) => new G(); void Main(string? s1, string? s2) { Run(CreateG(s1).M, s2)/*T:(string?, string?)*/; if (s1 == null) return; Run(CreateG(s1).M, s2)/*T:(string!, string?)*/; if (s2 == null) return; Run(CreateG(s1).M, s2)/*T:(string!, string!)*/; } (T, U) Run(MyDelegate del, U u) => del(u); } public class G { public T t = default(T)!; public (T, U) M(U u) => (t, u); } public delegate (T, U) MyDelegate(U u); "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(33638, "https://github.com/dotnet/roslyn/issues/33638")] [Fact] public void TupleFromNestedGenerics() { var source = @"public class G { public (T, U) M(T t, U u) => (t, u); } public class C { public (T, U) M(T t, U u) => (t, u); } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [WorkItem(30562, "https://github.com/dotnet/roslyn/issues/30562")] [Fact] public void NotNullAfterDereference_ForEach() { var source = @"class Enumerable { public System.Collections.IEnumerator GetEnumerator() => throw null!; } class Program { static void F1(object[]? x1, object[]? y1) { foreach (var x in x1) { } // 1 foreach (var x in x1) { } } static void F2(object[]? x1, object[]? y1) { foreach (var y in y1) { } // 2 y1.GetEnumerator(); } static void F3(Enumerable? x2, Enumerable? y2) { foreach (var x in x2) { } // 3 foreach (var x in x2) { } } static void F4(Enumerable? x2, Enumerable? y2) { y2.GetEnumerator(); // 4 foreach (var y in y2) { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in x1) { } // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(9, 27), // (14,27): warning CS8602: Dereference of a possibly null reference. // foreach (var y in y1) { } // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(14, 27), // (19,27): warning CS8602: Dereference of a possibly null reference. // foreach (var x in x2) { } // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(19, 27), // (24,9): warning CS8602: Dereference of a possibly null reference. // y2.GetEnumerator(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(24, 9)); } [Fact] public void SpecialAndWellKnownMemberLookup() { var source0 = @" namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public struct Int32 { } public class Type { } public struct Boolean { } public struct Enum { } public class Attribute { } public struct Nullable { public static implicit operator Nullable(T x) { throw null!; } public static explicit operator T(Nullable x) { throw null!; } } namespace Collections.Generic { public class EqualityComparer { public static EqualityComparer Default => throw null!; } } } "; var comp = CreateEmptyCompilation(new[] { source0 }, options: WithNonNullTypesTrue()); var implicitOp = comp.GetSpecialTypeMember(SpecialMember.System_Nullable_T__op_Implicit_FromT); var explicitOp = comp.GetSpecialTypeMember(SpecialMember.System_Nullable_T__op_Explicit_ToT); var getDefault = comp.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_EqualityComparer_T__get_Default); Assert.NotNull(implicitOp); Assert.NotNull(explicitOp); Assert.NotNull(getDefault); Assert.True(implicitOp.IsDefinition); Assert.True(explicitOp.IsDefinition); Assert.True(getDefault.IsDefinition); } [Fact] public void ExpressionTrees_ByRefDynamic() { string source = @" using System; using System.Linq.Expressions; class Program { static void Main() { Expression> e = x => Goo(ref x); } static void Goo(ref T x) { } } "; CompileAndVerify(source, targetFramework: TargetFramework.StandardAndCSharp, options: WithNonNullTypesTrue()); } [Fact] [WorkItem(30673, "https://github.com/dotnet/roslyn/issues/30673")] public void TypeSymbolGetHashCode_Annotated() { var text = @" class C where T : class { C M() => throw null!; } "; var comp = CreateNullableCompilation(text); var type = comp.GetMember("C"); Assert.Equal("C", type.ToTestDisplayString(includeNonNullable: true)); Assert.True(type.IsDefinition); var type2 = comp.GetMember("C.M").ReturnType; Assert.Equal("C", type2.ToTestDisplayString(includeNonNullable: true)); Assert.False(type2.IsDefinition); AssertHashCodesMatch(type, type2); } [Fact] [WorkItem(30673, "https://github.com/dotnet/roslyn/issues/30673")] public void TypeSymbolGetHashCode_NotAnnotated() { var text = @" class C where T : class { C M() => throw null!; } "; var comp = CreateNullableCompilation(text); var type = comp.GetMember("C"); Assert.Equal("C", type.ToTestDisplayString(includeNonNullable: true)); Assert.True(type.IsDefinition); var type2 = comp.GetMember("C.M").ReturnType; Assert.Equal("C", type2.ToTestDisplayString(includeNonNullable: true)); Assert.False(type2.IsDefinition); AssertHashCodesMatch(type, type2); } [Fact] [WorkItem(30673, "https://github.com/dotnet/roslyn/issues/30673")] public void TypeSymbolGetHashCode_ContainingType() { var text = @" class C where T : class { interface I { } } "; var comp = CreateNullableCompilation(text); var iDefinition = comp.GetMember("C.I"); Assert.Equal("C.I", iDefinition.ToTestDisplayString(includeNonNullable: true)); Assert.True(iDefinition.IsDefinition); var cDefinition = iDefinition.ContainingType; Assert.Equal("C", cDefinition.ToTestDisplayString(includeNonNullable: true)); Assert.True(cDefinition.IsDefinition); var c2 = cDefinition.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(cDefinition.TypeParameters.Single(), NullableAnnotation.NotAnnotated))); Assert.Equal("C", c2.ToTestDisplayString(includeNonNullable: true)); Assert.False(c2.IsDefinition); AssertHashCodesMatch(cDefinition, c2); var i2 = c2.GetTypeMember("I"); Assert.Equal("C.I", i2.ToTestDisplayString(includeNonNullable: true)); Assert.False(i2.IsDefinition); AssertHashCodesMatch(iDefinition, i2); var c3 = cDefinition.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(cDefinition.TypeParameters.Single(), NullableAnnotation.Annotated))); Assert.Equal("C", c3.ToTestDisplayString(includeNonNullable: true)); Assert.False(c3.IsDefinition); AssertHashCodesMatch(cDefinition, c3); var i3 = c3.GetTypeMember("I"); Assert.Equal("C.I", i3.ToTestDisplayString(includeNonNullable: true)); Assert.False(i3.IsDefinition); AssertHashCodesMatch(iDefinition, i3); } [Fact] [WorkItem(30673, "https://github.com/dotnet/roslyn/issues/30673")] public void TypeSymbolGetHashCode_ContainingType_GenericNestedType() { var text = @" class C where T : class { interface I where U : class { } } "; var comp = CreateNullableCompilation(text); var iDefinition = comp.GetMember("C.I"); Assert.Equal("C.I", iDefinition.ToTestDisplayString(includeNonNullable: true)); Assert.True(iDefinition.IsDefinition); // Construct from iDefinition with annotated U from iDefinition var i1 = iDefinition.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(iDefinition.TypeParameters.Single(), NullableAnnotation.Annotated))); Assert.Equal("C.I", i1.ToTestDisplayString(includeNonNullable: true)); AssertHashCodesMatch(iDefinition, i1); var cDefinition = iDefinition.ContainingType; Assert.Equal("C", cDefinition.ToTestDisplayString(includeNonNullable: true)); Assert.True(cDefinition.IsDefinition); // Construct from cDefinition with unannotated T from cDefinition var c2 = cDefinition.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(cDefinition.TypeParameters.Single(), NullableAnnotation.NotAnnotated))); var i2 = c2.GetTypeMember("I"); Assert.Equal("C.I", i2.ToTestDisplayString(includeNonNullable: true)); Assert.Same(i2.OriginalDefinition, iDefinition); AssertHashCodesMatch(i2, iDefinition); // Construct from i2 with U from iDefinition var i2a = i2.Construct(iDefinition.TypeParameters.Single()); Assert.Equal("C.I", i2a.ToTestDisplayString(includeNonNullable: true)); AssertHashCodesMatch(iDefinition, i2a); // Construct from i2 with annotated U from iDefinition var i2b = i2.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(iDefinition.TypeParameters.Single(), NullableAnnotation.Annotated))); Assert.Equal("C.I", i2b.ToTestDisplayString(includeNonNullable: true)); AssertHashCodesMatch(iDefinition, i2b); // Construct from i2 with U from i2 var i2c = i2.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(i2.TypeParameters.Single(), NullableAnnotation.Annotated))); Assert.Equal("C.I", i2c.ToTestDisplayString(includeNonNullable: true)); AssertHashCodesMatch(iDefinition, i2c); var c3 = cDefinition.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(cDefinition.TypeParameters.Single(), NullableAnnotation.Annotated))); var i3 = c3.GetTypeMember("I"); Assert.Equal("C.I", i3.ToTestDisplayString(includeNonNullable: true)); AssertHashCodesMatch(iDefinition, i3); var i3b = i3.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(i3.TypeParameters.Single(), NullableAnnotation.Annotated))); Assert.Equal("C.I", i3b.ToTestDisplayString(includeNonNullable: true)); AssertHashCodesMatch(iDefinition, i3b); // Construct from cDefinition with modified T from cDefinition var modifiers = ImmutableArray.Create(CSharpCustomModifier.CreateOptional(comp.GetSpecialType(SpecialType.System_Object))); var c4 = cDefinition.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(cDefinition.TypeParameters.Single(), customModifiers: modifiers))); Assert.Equal("C", c4.ToTestDisplayString()); Assert.False(c4.IsDefinition); AssertHashCodesMatch(cDefinition, c4); var i4 = c4.GetTypeMember("I"); Assert.Equal("C.I", i4.ToTestDisplayString()); Assert.Same(i4.OriginalDefinition, iDefinition); Assert.False(iDefinition.Equals(i4, TypeCompareKind.ConsiderEverything)); Assert.False(iDefinition.Equals(i4, TypeCompareKind.CLRSignatureCompareOptions)); Assert.True(iDefinition.Equals(i4, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); Assert.Equal(iDefinition.GetHashCode(), i4.GetHashCode()); } private static void AssertHashCodesMatch(TypeSymbol c, TypeSymbol c2) { Assert.False(c.Equals(c2)); Assert.True(c.Equals(c2, TypeCompareKind.AllIgnoreOptions)); Assert.Equal(c2.GetHashCode(), c.GetHashCode()); } [Fact] [WorkItem(35619, "https://github.com/dotnet/roslyn/issues/35619")] public void ExplicitInterface_UsingOuterDefinition_Simple() { var text = @" class Outer { protected internal interface Interface { void Method(); } internal class C : Outer.Interface { void Interface.Method() { } } } "; var comp = CreateNullableCompilation(text); comp.VerifyDiagnostics( // (10,14): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void Interface.Method() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "Interface").WithLocation(10, 14) ); } [Fact] [WorkItem(35619, "https://github.com/dotnet/roslyn/issues/35619")] public void ExplicitInterface_UsingOuterDefinition() { var text = @" class Outer where T : class { internal class Inner where U : class { protected internal interface Interface { void Method(); } // The implemented interface is Outer.Inner.Interface internal class Derived6 : Outer.Inner.Interface { // The explicit interface is Outer.Inner.Interface void Inner.Interface.Method() { } } } } "; CreateCompilation(text, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (14,18): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void Inner.Interface.Method() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "Inner.Interface").WithLocation(14, 18) ); } [Fact] [WorkItem(35619, "https://github.com/dotnet/roslyn/issues/35619")] public void ExplicitInterface_WithExplicitOuter() { var text = @" class Outer where T : class { internal class Inner where U : class { protected internal interface Interface { void Method(); } // The implemented interface is Outer.Inner.Interface internal class Derived6 : Outer.Inner.Interface { // The explicit interface is Outer.Inner.Interface void Outer.Inner.Interface.Method() { } } } } "; CreateCompilation(text, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] public void ExplicitInterface_WithExplicitOuter_DisabledT() { var text = @" class Outer where T : class { internal class Inner where U : class { protected internal interface Interface { void Method(); } // The implemented interface is Outer.Inner.Interface internal class Derived6 : Outer.Inner.Interface { // The explicit interface is Outer.Inner.Interface void Outer< #nullable disable T #nullable enable >.Inner.Interface.Method() { } } } } "; CreateCompilation(text, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (14,18): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void Outer< Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, @"Outer< #nullable disable T #nullable enable >.Inner.Interface").WithLocation(14, 18) ); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] public void ExplicitInterface_WithExplicitOuter_DisabledT_ImplementedInterfaceMatches() { var text = @" class Outer where T : class { internal class Inner where U : class { protected internal interface Interface { void Method(); } // The implemented interface is Outer.Inner.Interface internal class Derived6 : Inner.Interface { // The explicit interface is Outer.Inner.Interface void Outer< #nullable disable T #nullable enable >.Inner.Interface.Method() { } } } } "; CreateCompilation(text, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] public void TestErrorsImplementingGenericNestedInterfaces_Explicit() { var text = @" using System.Collections.Generic; class Outer { internal class Inner { protected internal interface Interface { T Property { set; } void Method(T a, U[] b, List c, Dictionary d); } internal class Derived4 { internal class Derived5 : Outer.Inner.Interface { T Outer.Inner.Interface.Property { set { } } void Inner.Interface.Method(T a, U[] b, List c, Dictionary D) { } } internal class Derived6 : Outer.Inner.Interface { T Outer.Inner.Interface.Property { set { } } void Inner.Interface.Method(T a, U[] b, List c, Dictionary D) { } } } } } "; CreateCompilation(text, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (14,39): error CS0535: 'Outer.Inner.Derived4.Derived5' does not implement interface member 'Outer.Inner.Interface.Method(T, U[], List, Dictionary)' // internal class Derived5 : Outer.Inner.Interface Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer.Inner.Interface").WithArguments("Outer.Inner.Derived4.Derived5", "Outer.Inner.Interface.Method(T, U[], System.Collections.Generic.List, System.Collections.Generic.Dictionary)").WithLocation(14, 39), // (20,22): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void Inner.Interface.Method(T a, U[] b, List c, Dictionary D) Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "Inner.Interface").WithLocation(20, 22), // (20,47): error CS0539: 'Outer.Inner.Derived4.Derived5.Method(T, U[], List, Dictionary)' in explicit interface declaration is not found among members of the interface that can be implemented // void Inner.Interface.Method(T a, U[] b, List c, Dictionary D) Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer.Inner.Derived4.Derived5.Method(T, U[], System.Collections.Generic.List, System.Collections.Generic.Dictionary)").WithLocation(20, 47), // (30,22): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void Inner.Interface.Method(T a, U[] b, List c, Dictionary D) Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "Inner.Interface").WithLocation(30, 22) ); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] public void TestErrorsImplementingGenericNestedInterfaces_Explicit_IncorrectPartialQualification() { var source = @" using System.Collections.Generic; class Outer { internal class Inner { protected internal interface Interface { T Property { set; } void Method(T a, U[] b, List c, Dictionary d); } internal class Derived3 : Interface { T Interface.Property { set { } } void Inner.Interface.Method(T a, U[] B, List C, Dictionary d) { } } } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (18,18): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void Inner.Interface.Method(T a, U[] B, List C, Dictionary d) Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "Inner.Interface").WithLocation(18, 18) ); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_01() { var source1 = @" public interface I1 { void M(); } public interface I2 : I1 { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2 { void I1.M() { } }"; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_02() { var source1 = @" public interface I1 { void M(); } public struct S { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2 { void I1>.M() { } } "; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_03() { var source1 = @" public interface I1 { void M(); } public class C1 { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2 { void I1>.M() { } } "; var expected = new DiagnosticDescription[] { // (4,10): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void I1>.M() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "I1>").WithLocation(4, 10) }; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(expected); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_04() { var source1 = @" public interface I1 { void M(); } public class C1 { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2, I1> { void I1>.M() { } } "; var expected = new DiagnosticDescription[] { // (2,7): warning CS8645: 'I1>' is already listed in the interface list on type 'C' with different nullability of reference types. // class C : I2, I1> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C").WithArguments("I1>", "C").WithLocation(2, 7) }; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(expected); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_05() { var source1 = @" public interface I1 { void M(); } public struct S { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2 { void I1 #nullable enable >.M() { } } "; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_06() { var source1 = @" public interface I1 { void M(); } public class C1 { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2 { void I1 #nullable enable >.M() { } } "; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_07() { var source1 = @" public interface I1 { void M(); } public interface I2 : I1<(I2T1, I2T2)> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2 { void I1<(CT1 a, CT2 b)>.M() { } } "; var expected = new DiagnosticDescription[] { // (4,10): error CS0540: 'C.I1<(CT1 a, CT2 b)>.M()': containing type does not implement interface 'I1<(CT1 a, CT2 b)>' // void I1<(CT1 a, CT2 b)>.M() Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I1<(CT1 a, CT2 b)>").WithArguments("C.I1<(CT1 a, CT2 b)>.M()", "I1<(CT1 a, CT2 b)>").WithLocation(4, 10) }; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(expected); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_08() { var source1 = @" public interface I1 { void M(); } public interface I2 : I1<(I2T1, I2T2)> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2, I1<(CT1 a, CT2 b)> { void I1<(CT1 c, CT2 d)>.M() { } } "; var expected = new DiagnosticDescription[] { // (2,7): error CS8140: 'I1<(CT1 a, CT2 b)>' is already listed in the interface list on type 'C' with different tuple element names, as 'I1<(CT1, CT2)>'. // class C : I2, I1<(CT1 a, CT2 b)> Diagnostic(ErrorCode.ERR_DuplicateInterfaceWithTupleNamesInBaseList, "C").WithArguments("I1<(CT1 a, CT2 b)>", "I1<(CT1, CT2)>", "C").WithLocation(2, 7), // (4,10): error CS0540: 'C.I1<(CT1 c, CT2 d)>.M()': containing type does not implement interface 'I1<(CT1 c, CT2 d)>' // void I1<(CT1 c, CT2 d)>.M() Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I1<(CT1 c, CT2 d)>").WithArguments("C.I1<(CT1 c, CT2 d)>.M()", "I1<(CT1 c, CT2 d)>").WithLocation(4, 10) }; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(expected); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_09() { var source1 = @" public interface I1 { void M(); } public class C1 { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2, #nullable disable I1> #nullable enable { void I1>.M() { } } "; var expected = new DiagnosticDescription[] { // (2,7): warning CS8645: 'I1>' is already listed in the interface list on type 'C' with different nullability of reference types. // class C : I2, Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "C").WithArguments("I1>", "C").WithLocation(2, 7), // (7,10): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void I1>.M() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "I1>").WithLocation(7, 10) }; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(expected); } [Fact] [WorkItem(30677, "https://github.com/dotnet/roslyn/issues/30677")] [WorkItem(31858, "https://github.com/dotnet/roslyn/issues/31858")] public void ExplictInterfaceImplementation_10() { var source1 = @" public interface I1 { void M(); } public class C1 { } public interface I2 : I1> { } "; var comp1 = CreateCompilation(source1, options: WithNonNullTypesFalse()); comp1.VerifyDiagnostics(); var source2 = @" class C : I2, I1 #nullable enable > { void I1>.M() { } } "; var expected = new DiagnosticDescription[] { // (9,10): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void I1>.M() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "I1>").WithLocation(9, 10) }; var comp2 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.EmitToImageReference() }); comp2.VerifyDiagnostics(expected); var comp3 = CreateCompilation(source2, options: WithNonNullTypesTrue(), references: new[] { comp1.ToMetadataReference() }); comp3.VerifyDiagnostics(expected); } [Fact] public void WriteOfReadonlyStaticMemberOfAnotherInstantiation01() { var text = @"public static class Goo { static Goo() { Goo.Y = 3; } public static int Y { get; } }"; CreateCompilation(text, options: WithNonNullTypesTrue(TestOptions.ReleaseDll)).VerifyDiagnostics(); CreateCompilation(text, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), parseOptions: TestOptions.Regular.WithStrictFeature()).VerifyDiagnostics(); } [Fact] public void TestOverrideGenericMethodWithTypeParamDiffNameWithCustomModifiers() { var text = @" namespace Metadata { using System; public class GD : Outer.Inner { public override void Method(string[] x, ulong[] y, X[] z) { Console.Write(""Hello {0}"", z.Length); } static void Main() { new GD().Method(null, null, new byte[] { 0, 127, 255 }); } } } "; var verifier = CompileAndVerify( text, new[] { TestReferences.SymbolsTests.CustomModifiers.Modifiers.dll }, options: WithNonNullTypesTrue(TestOptions.ReleaseExe), expectedOutput: @"Hello 3", expectedSignatures: new[] { // The ILDASM output is following, and Roslyn handles it correctly. // Verifier tool gives different output due to the limitation of Reflection // @".method public hidebysig virtual instance System.Void Method(" + // @"System.String modopt([mscorlib]System.Runtime.CompilerServices.IsConst)[] modopt([mscorlib]System.Runtime.CompilerServices.IsConst) x," + // @"UInt64 modopt([mscorlib]System.Runtime.CompilerServices.IsConst)[] modopt([mscorlib]System.Runtime.CompilerServices.IsConst) y," + // @"!!X modopt([mscorlib]System.Runtime.CompilerServices.IsConst)[] modopt([mscorlib]System.Runtime.CompilerServices.IsConst) z) cil managed") Signature("Metadata.GD", "Method", @".method public hidebysig virtual instance System.Void Method(" + @"modopt(System.Runtime.CompilerServices.IsConst) System.String[] x, " + @"modopt(System.Runtime.CompilerServices.IsConst) System.UInt64[] y, "+ @"modopt(System.Runtime.CompilerServices.IsConst) X[] z) cil managed"), }, symbolValidator: module => { var expected = @"[NullableContext(1)] [Nullable({ 0, 1 })] Metadata.GD void Method(System.String![]! x, System.UInt64[]! y, X[]! z) [Nullable(0)] X System.String![]! x System.UInt64[]! y X[]! z GD() "; var actual = NullableAttributesVisitor.GetString((PEModuleSymbol)module); AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, actual); }); } [Fact] [WorkItem(30747, "https://github.com/dotnet/roslyn/issues/30747")] public void MissingTypeKindBasisTypes() { var source1 = @" public struct A {} public enum B {} public class C {} public delegate void D(); public interface I1 {} "; var compilation1 = CreateEmptyCompilation(source1, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { MinCorlibRef }); compilation1.VerifyEmitDiagnostics(); Assert.Equal(TypeKind.Struct, compilation1.GetTypeByMetadataName("A").TypeKind); Assert.Equal(TypeKind.Enum, compilation1.GetTypeByMetadataName("B").TypeKind); Assert.Equal(TypeKind.Class, compilation1.GetTypeByMetadataName("C").TypeKind); Assert.Equal(TypeKind.Delegate, compilation1.GetTypeByMetadataName("D").TypeKind); Assert.Equal(TypeKind.Interface, compilation1.GetTypeByMetadataName("I1").TypeKind); var source2 = @" interface I2 { I1 M(A a, B b, C c, D d); } "; var compilation2 = CreateEmptyCompilation(source2, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { compilation1.EmitToImageReference(), MinCorlibRef }); compilation2.VerifyEmitDiagnostics(); // Verification against a corlib not named exactly mscorlib is expected to fail. CompileAndVerify(compilation2, verify: Verification.Fails); Assert.Equal(TypeKind.Struct, compilation2.GetTypeByMetadataName("A").TypeKind); Assert.Equal(TypeKind.Enum, compilation2.GetTypeByMetadataName("B").TypeKind); Assert.Equal(TypeKind.Class, compilation2.GetTypeByMetadataName("C").TypeKind); Assert.Equal(TypeKind.Delegate, compilation2.GetTypeByMetadataName("D").TypeKind); Assert.Equal(TypeKind.Interface, compilation2.GetTypeByMetadataName("I1").TypeKind); var compilation3 = CreateEmptyCompilation(source2, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { compilation1.ToMetadataReference(), MinCorlibRef }); compilation3.VerifyEmitDiagnostics(); CompileAndVerify(compilation3, verify: Verification.Fails); Assert.Equal(TypeKind.Struct, compilation3.GetTypeByMetadataName("A").TypeKind); Assert.Equal(TypeKind.Enum, compilation3.GetTypeByMetadataName("B").TypeKind); Assert.Equal(TypeKind.Class, compilation3.GetTypeByMetadataName("C").TypeKind); Assert.Equal(TypeKind.Delegate, compilation3.GetTypeByMetadataName("D").TypeKind); Assert.Equal(TypeKind.Interface, compilation3.GetTypeByMetadataName("I1").TypeKind); var compilation4 = CreateEmptyCompilation(source2, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { compilation1.EmitToImageReference() }); compilation4.VerifyDiagnostics( // (4,10): error CS0012: The type 'ValueType' is defined in an assembly that is not referenced. You must add a reference to assembly 'mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2'. // I1 M(A a, B b, C c, D d); Diagnostic(ErrorCode.ERR_NoTypeDef, "A").WithArguments("System.ValueType", "mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2").WithLocation(4, 10), // (4,15): error CS0012: The type 'Enum' is defined in an assembly that is not referenced. You must add a reference to assembly 'mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2'. // I1 M(A a, B b, C c, D d); Diagnostic(ErrorCode.ERR_NoTypeDef, "B").WithArguments("System.Enum", "mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2").WithLocation(4, 15), // (4,25): error CS0012: The type 'MulticastDelegate' is defined in an assembly that is not referenced. You must add a reference to assembly 'mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2'. // I1 M(A a, B b, C c, D d); Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("System.MulticastDelegate", "mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2").WithLocation(4, 25) ); var a = compilation4.GetTypeByMetadataName("A"); var b = compilation4.GetTypeByMetadataName("B"); var c = compilation4.GetTypeByMetadataName("C"); var d = compilation4.GetTypeByMetadataName("D"); var i1 = compilation4.GetTypeByMetadataName("I1"); Assert.Equal(TypeKind.Class, a.TypeKind); Assert.NotNull(a.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Class, b.TypeKind); Assert.NotNull(b.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Class, c.TypeKind); Assert.Null(c.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Class, d.TypeKind); Assert.NotNull(d.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Interface, i1.TypeKind); Assert.Null(i1.GetUseSiteDiagnostic()); var compilation5 = CreateEmptyCompilation(source2, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { compilation1.ToMetadataReference() }); compilation5.VerifyEmitDiagnostics( // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1), // error CS0518: Predefined type 'System.Attribute' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), // error CS0518: Predefined type 'System.Attribute' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), // error CS0518: Predefined type 'System.Byte' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Byte").WithLocation(1, 1), // error CS0518: Predefined type 'System.Attribute' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), // error CS0518: Predefined type 'System.Byte' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Byte").WithLocation(1, 1)); var compilation6 = CreateEmptyCompilation(source2, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { compilation1.EmitToImageReference(), MscorlibRef }); compilation6.VerifyDiagnostics( // (4,10): error CS0012: The type 'ValueType' is defined in an assembly that is not referenced. You must add a reference to assembly 'mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2'. // I1 M(A a, B b, C c, D d); Diagnostic(ErrorCode.ERR_NoTypeDef, "A").WithArguments("System.ValueType", "mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2").WithLocation(4, 10), // (4,15): error CS0012: The type 'Enum' is defined in an assembly that is not referenced. You must add a reference to assembly 'mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2'. // I1 M(A a, B b, C c, D d); Diagnostic(ErrorCode.ERR_NoTypeDef, "B").WithArguments("System.Enum", "mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2").WithLocation(4, 15), // (4,25): error CS0012: The type 'MulticastDelegate' is defined in an assembly that is not referenced. You must add a reference to assembly 'mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2'. // I1 M(A a, B b, C c, D d); Diagnostic(ErrorCode.ERR_NoTypeDef, "D").WithArguments("System.MulticastDelegate", "mincorlib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2").WithLocation(4, 25) ); a = compilation6.GetTypeByMetadataName("A"); b = compilation6.GetTypeByMetadataName("B"); c = compilation6.GetTypeByMetadataName("C"); d = compilation6.GetTypeByMetadataName("D"); i1 = compilation6.GetTypeByMetadataName("I1"); Assert.Equal(TypeKind.Class, a.TypeKind); Assert.NotNull(a.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Class, b.TypeKind); Assert.NotNull(b.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Class, c.TypeKind); Assert.Null(c.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Class, d.TypeKind); Assert.NotNull(d.GetUseSiteDiagnostic()); Assert.Equal(TypeKind.Interface, i1.TypeKind); Assert.Null(i1.GetUseSiteDiagnostic()); var compilation7 = CreateEmptyCompilation(source2, options: WithNonNullTypesTrue(TestOptions.ReleaseDll), references: new[] { compilation1.ToMetadataReference(), MscorlibRef }); compilation7.VerifyEmitDiagnostics(); CompileAndVerify(compilation7); Assert.Equal(TypeKind.Struct, compilation7.GetTypeByMetadataName("A").TypeKind); Assert.Equal(TypeKind.Enum, compilation7.GetTypeByMetadataName("B").TypeKind); Assert.Equal(TypeKind.Class, compilation7.GetTypeByMetadataName("C").TypeKind); Assert.Equal(TypeKind.Delegate, compilation7.GetTypeByMetadataName("D").TypeKind); Assert.Equal(TypeKind.Interface, compilation7.GetTypeByMetadataName("I1").TypeKind); } [Fact] public void AccessPropertyWithoutArguments() { var source1 = @"Imports System Imports System.Runtime.InteropServices Public Interface I Property Value(Optional index As Object = Nothing) As Object End Interface"; var ref1 = BasicCompilationUtils.CompileToMetadata(source1); var source2 = @"class C : I { public dynamic get_Value(object index = null) => ""Test""; public void set_Value(object index = null, object value = null) { } } class Test { static void Main() { I x = new C(); System.Console.WriteLine(x.Value.Length); } }"; var comp = CreateCompilation(source2, new[] { ref1.WithEmbedInteropTypes(true), CSharpRef }, options: WithNonNullTypesTrue(TestOptions.ReleaseExe)); CompileAndVerify(comp, expectedOutput: "4"); } [Fact] public void NullabilityOfTypeParameters_001() { var source = @" class Outer { void M(T x) { object y; y = x; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13) ); } [Fact] public void NullabilityOfTypeParameters_002() { var source = @" class Outer { void M(T x) { dynamic y; y = x; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13) ); } [Fact] public void NullabilityOfTypeParameters_003() { var source = @" class Outer { void M(T x) where T : I1 { object y; y = x; dynamic z; z = x; } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_004() { var source = @" class Outer { void M(U x) where U : T { T y; y = x; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_005() { var source = @" class Outer { void M(T x) { if (x == null) return; object y; y = x; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_006() { var source = @" class Outer { void M(T x) { if (x == null) return; dynamic y; y = x; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_007() { var source = @" class Outer { T M0(T x0, T y0) { if (x0 == null) throw null!; M2(x0) = x0; M2(x0) = y0; M2(x0).ToString(); M2(x0).ToString(); throw null!; } void M1(object? x1, object? y1) { if (x1 == null) return; M2(x1) = x1; M2(x1) = y1; } ref U M2(U a) where U : notnull => throw null!; } "; // Note: you cannot pass a `T` to a `U : object` even if the `T` was null-tested CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(x0) = x0; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(U)", "U", "T").WithLocation(7, 9), // (8,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(x0) = y0; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(U)", "U", "T").WithLocation(8, 9), // (10,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(U)", "U", "T").WithLocation(10, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(10, 9), // (11,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(U)", "U", "T").WithLocation(11, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(11, 9), // (19,18): warning CS8601: Possible null reference assignment. // M2(x1) = y1; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y1").WithLocation(19, 18) ); } [Fact] public void NullabilityOfTypeParameters_008() { var source = @" class Outer { void M0(T x0, U y0, U z0) where U : T { if (x0 == null) return; if (y0 == null) return; M2(x0) = y0; M2(x0) = z0; M2(x0) = y0; M2(x0) = z0; M2(x0).ToString(); M2(x0).ToString(); } ref U M2(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(13, 9) ); } [Fact] public void NullabilityOfTypeParameters_009() { var source = @" class Outer { void M0(T x0, T y0) { x0 = y0; } void M1(T y1) { T x1 = y1; x1 = y1; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_010() { var source = @" class Outer { void M0(Outer x0, T y0) where T : Outer? { x0 = y0; } void M1(T y1) where T : Outer? { Outer x1 = y1; x1 = y1; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x0 = y0; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y0").WithLocation(6, 14), // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer x1 = y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(11, 20), // (12,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x1 = y1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y1").WithLocation(12, 14) ); } [Fact] public void NullabilityOfTypeParameters_011() { var source = @" class Outer { void M0(Outer x0, T y0) where T : Outer? { if (y0 == null) return; x0 = y0; } void M1(T y1) where T : Outer? { if (y1 == null) return; Outer x1 = y1; x1 = y1; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] [WorkItem(30938, "https://github.com/dotnet/roslyn/issues/30938")] public void NullabilityOfTypeParameters_012() { var source = @" class Outer { void M(object? x, object y) { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // z = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("object", "T").WithLocation(8, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9)); } [Fact] [WorkItem(30938, "https://github.com/dotnet/roslyn/issues/30938")] public void NullabilityOfTypeParameters_013() { var source = @" class Outer { void M(dynamic? x, dynamic y) { T z; z = x; // 1 z = y; z = (T)x; // 2 z.ToString(); // 3 z = (T)y; z.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): warning CS8601: Possible null reference assignment. // z = x; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_014() { var source = @" class Outer { void M(object? x, object y) where T : I1 { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // z = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("object", "T").WithLocation(8, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9)); } [Fact] public void NullabilityOfTypeParameters_015() { var source = @" class Outer { void M(dynamic? x, dynamic y) where T : I1 { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): warning CS8601: Possible null reference assignment. // z = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_016() { var source = @" class Outer { void M(object? x, object y) where T : I1? { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // z = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("object", "T").WithLocation(8, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9)); } [Fact] public void NullabilityOfTypeParameters_017() { var source = @" class Outer { void M(dynamic? x, dynamic y) where T : I1? { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): warning CS8601: Possible null reference assignment. // z = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_018() { var source = @" class Outer { void M(T x) where U : T { U y; y = x; y = (U)x; y.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // y = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): warning CS8601: Possible null reference assignment. // y = (U)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x").WithLocation(8, 13), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_019() { var source = @" class Outer { void M(T x) where U : T, I1 { U y; y = x; y = (U)x; y.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // y = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): warning CS8601: Possible null reference assignment. // y = (U)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x").WithLocation(8, 13), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_020() { var source = @" class Outer { void M(T x) where U : T, I1? { U y; y = x; y = (U)x; y.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // y = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): warning CS8601: Possible null reference assignment. // y = (U)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x").WithLocation(8, 13), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_021() { var source = @" class Outer { void M(T x) where U : T where T : I1 { U y; y = x; y = (U)x; y.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'T' to 'U'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T", "U").WithLocation(7, 13) ); } [Fact] public void NullabilityOfTypeParameters_022() { var source = @" class Outer { void M(object? x) { if (x == null) return; T y; y = x; y = (T)x; y.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,13): error CS0266: Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "T").WithLocation(8, 13) ); } [Fact] [WorkItem(30939, "https://github.com/dotnet/roslyn/issues/30939")] public void NullabilityOfTypeParameters_023() { var source = @" class Outer { void M1(dynamic? x) { if (x == null) return; T y; y = x; y = (T)x; y.ToString(); } void M2(dynamic? x) { if (x != null) return; T y; y = x; // 1 y = (T)x; // 2 y.ToString(); // 3 } void M3(dynamic? x) { if (x != null) { T y; y = x; y = (T)x; y.ToString(); } else { T y; y = x; // 4 y = (T)x; // 5 y.ToString(); // 6 } } void M4(dynamic? x) { if (x == null) { T y; y = x; // 7 y = (T)x; // 8 y.ToString(); // 9 } else { T y; y = x; y = (T)x; y.ToString(); } } void M5(dynamic? x) { // Since `||` here could be a user-defined `operator |` invocation, // no reasonable inferences can be made. if (x == null || false) { T y; y = x; // 10 y = (T)x; // 11 y.ToString(); // 12 } else { T y; y = x; // 13 y = (T)x; // 14 y.ToString(); // 15 } } void M6(dynamic? x) { // Since `&&` here could be a user-defined `operator &` invocation, // no reasonable inferences can be made. if (x == null && true) { T y; y = x; // 16 y = (T)x; // 17 y.ToString(); // 18 } else { T y; y = x; // 19 y = (T)x; // 20 y.ToString(); // 21 } } void M7(dynamic? x) { if (!(x == null)) { T y; y = x; y = (T)x; y.ToString(); } else { T y; y = x; // 22 y = (T)x; // 23 y.ToString(); // 24 } } void M8(dynamic? x) { if (!(x != null)) { T y; y = x; // 25 y = (T)x; // 26 y.ToString(); // 27 } else { T y; y = x; y = (T)x; y.ToString(); } } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (16,13): warning CS8601: Possible null reference assignment. // y = x; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(16, 13), // (17,13): warning CS8601: Possible null reference assignment. // y = (T)x; // 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(17, 13), // (18,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(18, 9), // (32,17): warning CS8601: Possible null reference assignment. // y = x; // 4 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(32, 17), // (33,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 5 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(33, 17), // (34,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(34, 13), // (42,17): warning CS8601: Possible null reference assignment. // y = x; // 7 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(42, 17), // (43,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 8 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(43, 17), // (44,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(44, 13), // (61,17): warning CS8601: Possible null reference assignment. // y = x; // 10 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(61, 17), // (62,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 11 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(62, 17), // (63,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(63, 13), // (68,17): warning CS8601: Possible null reference assignment. // y = x; // 13 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(68, 17), // (69,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 14 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(69, 17), // (70,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 15 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(70, 13), // (80,17): warning CS8601: Possible null reference assignment. // y = x; // 16 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(80, 17), // (81,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 17 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(81, 17), // (82,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 18 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(82, 13), // (87,17): warning CS8601: Possible null reference assignment. // y = x; // 19 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(87, 17), // (88,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 20 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(88, 17), // (89,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 21 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(89, 13), // (104,17): warning CS8601: Possible null reference assignment. // y = x; // 22 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(104, 17), // (105,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 23 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(105, 17), // (106,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 24 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(106, 13), // (114,17): warning CS8601: Possible null reference assignment. // y = x; // 25 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(114, 17), // (115,17): warning CS8601: Possible null reference assignment. // y = (T)x; // 26 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(115, 17), // (116,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 27 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(116, 13)); } [Fact] [WorkItem(30939, "https://github.com/dotnet/roslyn/issues/30939")] public void DynamicControlTest() { var source = @" class Outer { void M1(dynamic? x) { if (x == null) return; string y; y = x; y = (string)x; y.ToString(); } void M2(dynamic? x) { if (x != null) return; string y; y = x; // 1 y = (string)x; // 2 y.ToString(); // 3 } void M3(dynamic? x) { if (x != null) { string y; y = x; y = (string)x; y.ToString(); } else { string y; y = x; // 4 y = (string)x; // 5 y.ToString(); // 6 } } void M4(dynamic? x) { if (x == null) { string y; y = x; // 7 y = (string)x; // 8 y.ToString(); // 9 } else { string y; y = x; y = (string)x; y.ToString(); } } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (16,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(16, 13), // (17,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = (string)x; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)x").WithLocation(17, 13), // (18,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(18, 9), // (32,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(32, 17), // (33,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = (string)x; // 5 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)x").WithLocation(33, 17), // (34,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(34, 13), // (42,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = x; // 7 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(42, 17), // (43,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = (string)x; // 8 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(string)x").WithLocation(43, 17), // (44,13): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(44, 13)); } [Fact] [WorkItem(30940, "https://github.com/dotnet/roslyn/issues/30940")] [WorkItem(30941, "https://github.com/dotnet/roslyn/issues/30941")] public void NullabilityOfTypeParameters_024() { var source = @" class Outer { void M(Outer? x, Outer y) where T : Outer? { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("Outer", "T").WithLocation(7, 13), // (7,13): warning CS8601: Possible null reference assignment. // z = x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("Outer", "T").WithLocation(8, 13), // (9,13): warning CS8601: Possible null reference assignment. // z = (T)x; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) ); } [Fact] [WorkItem(30940, "https://github.com/dotnet/roslyn/issues/30940")] public void NullabilityOfTypeParameters_025() { var source = @" class Outer { void M(Outer? x) where T : Outer? { if (x == null) return; T y; y = x; y = (T)x; y.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("Outer", "T").WithLocation(8, 13) ); } [Fact] [WorkItem(30940, "https://github.com/dotnet/roslyn/issues/30940")] [WorkItem(30941, "https://github.com/dotnet/roslyn/issues/30941")] public void NullabilityOfTypeParameters_026() { var source = @" class Outer { void M(Outer? x, Outer y) where T : Outer { T z; z = x; z = y; z = (T)x; z.ToString(); // 1 z = (T)y; z.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("Outer", "T").WithLocation(7, 13), // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // z = x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(7, 13), // (8,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // z = y; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "y").WithArguments("Outer", "T").WithLocation(8, 13), // (9,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // z = (T)x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)x").WithLocation(9, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9) ); } [Fact] [WorkItem(30940, "https://github.com/dotnet/roslyn/issues/30940")] public void NullabilityOfTypeParameters_027() { var source = @" class Outer { void M(Outer? x) where T : Outer { if (x == null) return; T y; y = x; y = (T)x; y.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,13): error CS0266: Cannot implicitly convert type 'Outer' to 'T'. An explicit conversion exists (are you missing a cast?) // y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("Outer", "T").WithLocation(8, 13) ); } [Fact] public void NullabilityOfTypeParameters_028() { var source = @" class Outer { void M0(Outer x0, T y0) where T : Outer { x0 = y0; } void M1(T y1) where T : Outer { Outer x1 = y1; x1 = y1; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_029() { var source = @" class Outer { void M0(T x) { x = default; x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_030() { var source = @" class Outer { void M0(T x) { x = default(T); x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default(T); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_031() { var source = @" class Outer { void M0(T x) where T : I1? { x = default; x.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_032() { var source = @" class Outer { void M0(T x) where T : I1? { x = default(T); x.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default(T); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_033() { var source = @" class Outer { void M0(T x) where T : Outer { x = default; x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = default; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_034() { var source = @" class Outer { void M0(T x) where T : Outer { x = default(T); x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = default(T); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_035() { var source = @" class Outer { void M0(T x) where T : I1 { x = default; x.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_036() { var source = @" class Outer { void M0(T x) where T : I1 { x = default(T); x.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x = default(T); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_037() { var source = @" class Outer { void M0(T x) { x.ToString(); x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9) ); } [Fact] public void NullabilityOfTypeParameters_038() { var source = @" class Outer { void M0(T x) where T : I1? { x.ToString(); x.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9) ); } [Fact] public void NullabilityOfTypeParameters_039() { var source = @" class Outer { void M0(T x) where T : I1 { x.ToString(); x.ToString(); } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_040() { var source = @" class Outer { void M0(T x) where T : Outer? { x.ToString(); x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9) ); } [Fact] public void NullabilityOfTypeParameters_041() { var source = @" class Outer { void M0(T x) where T : Outer { x.ToString(); x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_042() { var source = @" class Outer { void M0(T x) { M1(x); M1(x); } void M1(T x) where T : notnull {} } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8714: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(6, 9), // (7,9): warning CS8714: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_043() { var source = @" class Outer { void M0(T x) { if (x == null) return; M1(x); M1(x); } void M1(T x) where T : notnull {} } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8714: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(7, 9), // (8,9): warning CS8714: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_044() { var source = @" class Outer { void M0(T x) where T : class? { M1(x); M1(x); } void M1(T x) where T : class {} } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8634: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'class' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(6, 9), // (7,9): warning CS8634: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'class' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_045() { var source = @" class Outer { void M0(T x) where T : class? { if (x == null) return; M1(x); M1(x); } void M1(T x) where T : class {} } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8634: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'class' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(7, 9), // (8,9): warning CS8634: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Outer.M1(T)'. Nullability of type argument 'T' doesn't match 'class' constraint. // M1(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "M1").WithArguments("Outer.M1(T)", "T", "T").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_046() { var source = @" class Outer { void M0(T x) where T : class? { x = null; x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // x = null; Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9)); } [Fact] public void NullabilityOfTypeParameters_047() { var source = @" class Outer { void M0(T x) where T : class { x = null; x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_048() { var source = @" class Outer { void M0(T x) where T : Outer? { x = null; x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // x = null; Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9)); } [Fact] public void NullabilityOfTypeParameters_049() { var source = @" class Outer { void M0(T x) where T : Outer { x = null; x.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_050() { var source = @" class Outer { void M0(T x) { M1(x, x).ToString(); } T M1(T x, T y) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // M1(x, x).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x, x)").WithLocation(6, 9) ); } [Fact] public void NullabilityOfTypeParameters_051() { var source = @" class Outer { void M0(T x, T y) { if (x == null) return; M1(x, y).ToString(); } T M1(T x, T y) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // M1(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x, y)").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_052() { var source = @" class Outer { void M0(T x, T y) { if (y == null) return; M1(x, y).ToString(); } T M1(T x, T y) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // M1(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x, y)").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_053() { var source = @" class Outer { void M0(T x, T y) { if (x == null) return; if (y == null) return; M1(x, y).ToString(); M1(x, y).ToString(); } T M1(T x, T y) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M1(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x, y)").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // M1(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x, y)").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_054() { var source = @" class Outer { void M0(T x, object y) { M1(x, y).ToString(); } T M1(T x, T y) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,12): warning CS8604: Possible null reference argument for parameter 'x' in 'object Outer.M1(object x, object y)'. // M1(x, y).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("x", "object Outer.M1(object x, object y)").WithLocation(6, 12) ); } [Fact] public void NullabilityOfTypeParameters_055() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { M2(x0, y0) = z0; } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_056() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; M2(x0, y0) = z0; M2(x0, y0).ToString(); } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M2(x0, y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0, y0)").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_057() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (y0 == null) return; M2(x0, y0) = z0; } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_058() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; if (y0 == null) return; M2(x0, y0) = z0; M2(x0, y0) = z0; M2(x0, y0).ToString(); } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M2(x0, y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0, y0)").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_059() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T, I1 { if (x0 == null) return; if (y0 == null) return; M2(x0, y0) = z0; } ref U M2(U a, U b) => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_060() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : class, T { if (x0 == null) return; if (y0 == null) return; M2(x0, y0) = z0; } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_061() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; if (y0 == null) return; if (z0 == null) return; M2(x0, y0) = z0; } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_062() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { M2(out x0, out y0) = z0; } ref U M2(out U a, out U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_063() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; M2(out M3(x0), out y0) = z0; M2(out M3(x0), out y0); M2(out M3(x0), out y0); M2(out M3(x0), out y0); M2(out M3(x0), out y0).ToString(); M2(out M3(x0), out y0).ToString(); } ref U M2(out U a, out U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // M2(out M3(x0), out y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(out M3(x0), out y0)").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // M2(out M3(x0), out y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(out M3(x0), out y0)").WithLocation(13, 9) ); } [Fact] public void NullabilityOfTypeParameters_064() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (y0 == null) return; M2(out x0, out M3(y0)) = z0; M2(out x0, out M3(y0)); M2(out x0, out M3(y0)); M2(out x0, out M3(y0)); M2(out x0, out M3(y0)).ToString(); // warn M2(out x0, out M3(y0)).ToString(); // warn } ref U M2(out U a, out U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // M2(out x0, out M3(y0)).ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(out x0, out M3(y0))").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // M2(out x0, out M3(y0)).ToString(); // warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(out x0, out M3(y0))").WithLocation(13, 9) ); } [Fact] public void NullabilityOfTypeParameters_065() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; if (y0 == null) return; M2(out M3(x0), out M3(y0)) = z0; M2(out M3(x0), out M3(y0)) = z0; M2(out M3(x0), out M3(y0)) = z0; M2(out M3(x0), out M3(y0)) = z0; M2(out M3(x0), out M3(y0)).ToString(); } ref U M2(out U a, out U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // M2(out M3(x0), out M3(y0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(out M3(x0), out M3(y0))").WithLocation(12, 9) ); } [Fact] public void NullabilityOfTypeParameters_066() { var source = @" class Outer { void M0(T x0, object? y0) { object? z0 = new object(); z0 = x0; M2(out y0, out M3(z0)).ToString(); } ref U M2(out U a, out U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M2(out y0, out M3(z0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(out y0, out M3(z0))").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_067() { var source = @" class Outer { void M0(T x0, object? y0) { object? z0 = new object(); z0 = x0; M2(y0, z0).ToString(); } ref U M2(U a, U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M2(y0, z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(y0, z0)").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_068() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T where T : class? { M2(M3(x0), M3(y0)) = z0; } ref U M2(I1 a, I1 b) => throw null!; I1 M3(U a) => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_069() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T where T : class? { if (x0 == null) return; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)).ToString(); } ref U M2(I1 a, I1 b) => throw null!; I1 M3(U a) => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M2(M3(x0), M3(y0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(M3(x0), M3(y0))").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_070() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T where T : class? { if (y0 == null) return; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)).ToString(); } ref U M2(I1 a, I1 b) => throw null!; I1 M3(U a) => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M2(M3(x0), M3(y0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(M3(x0), M3(y0))").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_071() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T where T : class? { if (x0 == null) return; if (y0 == null) return; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)) = z0; M2(M3(x0), M3(y0)).ToString(); } ref U M2(I1 a, I1 b) => throw null!; I1 M3(U a) => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,9): warning CS8602: Dereference of a possibly null reference. // M2(M3(x0), M3(y0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(M3(x0), M3(y0))").WithLocation(12, 9) ); } [Fact] public void NullabilityOfTypeParameters_072() { var source = @" class Outer { void M0(T x0, I1 y0) { object? z0 = new object(); z0 = x0; M2(y0, M3(z0)).ToString(); } ref U M2(I1 a, I1 b) => throw null!; I1 M3(U a) => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M2(y0, M3(z0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(y0, M3(z0))").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_073() { var source = @" class Outer { void M0(object x0, T y0) { if (y0 == null) return; object? z0 = new object(); z0 = y0; M2(out x0, out M3(z0)).ToString(); } ref U M2(out U a, out U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_074() { var source = @" class Outer { void M0(object x0, T y0) { if (y0 == null) return; object? z0 = new object(); z0 = y0; M2(out M3(z0), out x0).ToString(); } ref U M2(out U a, out U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_075() { var source = @" class Outer { void M0() where T : new() { T x0; x0 = new T(); x0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_076() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { M2(ref x0, ref y0) = z0; } ref U M2(ref U a, ref U b) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_077() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; M2(ref M3(x0), ref y0) = z0; M2(ref M3(x0), ref y0); M2(ref M3(x0), ref y0).ToString(); } ref U M2(ref U a, ref U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M2(ref M3(x0), ref y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(ref M3(x0), ref y0)").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_078() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (y0 == null) return; M2(ref x0, ref M3(y0)) = z0; M2(ref x0, ref M3(y0)); M2(ref x0, ref M3(y0)).ToString(); } ref U M2(ref U a, ref U b) => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M2(ref x0, ref M3(y0)).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(ref x0, ref M3(y0))").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_079() { var source = @" class Outer { void M0(T x0, T y0, U z0) where U : T { if (x0 == null) return; if (y0 == null) return; M2(ref M3(x0), ref M3(y0)) = z0; M2(ref M3(x0), ref M3(y0)) = z0; } ref U M2(ref U a, ref U b) where U : notnull => throw null!; ref U M3(U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(ref U, ref U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(ref M3(x0), ref M3(y0)) = z0; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(ref U, ref U)", "U", "T").WithLocation(8, 9), // (9,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(ref U, ref U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(ref M3(x0), ref M3(y0)) = z0; Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(ref U, ref U)", "U", "T").WithLocation(9, 9) ); } [Fact] [WorkItem(30946, "https://github.com/dotnet/roslyn/issues/30946")] public void NullabilityOfTypeParameters_080() { var source = @" class Outer { void M0(T x0, T y0) { if (x0 == null) return; M2(x0).M3(ref y0); M2(x0).M3(ref y0); } Other M2(U a) where U : notnull => throw null!; } class Other where U : notnull { public void M3(ref U a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(x0).M3(ref y0); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(U)", "U", "T").WithLocation(7, 9), // (8,9): warning CS8714: The type 'T' cannot be used as type parameter 'U' in the generic type or method 'Outer.M2(U)'. Nullability of type argument 'T' doesn't match 'notnull' constraint. // M2(x0).M3(ref y0); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "M2").WithArguments("Outer.M2(U)", "U", "T").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_081() { var source = @" class Outer { void M0(T x0) { M2(x0); } void M2(object a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,12): warning CS8604: Possible null reference argument for parameter 'a' in 'void Outer.M2(object a)'. // M2(x0); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x0").WithArguments("a", "void Outer.M2(object a)").WithLocation(6, 12) ); } [Fact] public void NullabilityOfTypeParameters_082() { var source = @" class Outer { void M0(T x0) { M2(x0); } void M2(in object a) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,12): warning CS8604: Possible null reference argument for parameter 'a' in 'void Outer.M2(in object a)'. // M2(x0); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x0").WithArguments("a", "void Outer.M2(in object a)").WithLocation(6, 12) ); } [Fact] public void NullabilityOfTypeParameters_083() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0) where T : class? { M3(M2(x0)); M3>(y0); M3>(z0); } I1 M2(U a) => throw null!; void M3(U a) where U : I1 => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3(M2(x0)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3").WithArguments("Outer.M3(U)", "I1", "U", "I1").WithLocation(6, 9), // (7,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3>(y0); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3>").WithArguments("Outer.M3(U)", "I1", "U", "I1").WithLocation(7, 9), // (8,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3>(z0); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3>").WithArguments("Outer.M3(U)", "I1", "U", "I1").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_084() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0, U? a0) where T : class? where U : class, T { M3(M2(x0), a0); if (x0 == null) return; M3(M2(x0), a0); M3, U>(y0, null); M3, string>(z0, null); } I1 M2(U a) => throw null!; void M3(U a, W? b) where U : I1 where W : class => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U, W?)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3(M2(x0), a0); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3").WithArguments("Outer.M3(U, W?)", "I1", "U", "I1").WithLocation(6, 9), // (9,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U, W?)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3(M2(x0), a0); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3").WithArguments("Outer.M3(U, W?)", "I1", "U", "I1").WithLocation(9, 9), // (11,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U, W?)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3, U>(y0, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3, U>").WithArguments("Outer.M3(U, W?)", "I1", "U", "I1").WithLocation(11, 9), // (12,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U, W?)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3, string>(z0, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3, string>").WithArguments("Outer.M3(U, W?)", "I1", "U", "I1").WithLocation(12, 9) ); } [Fact] public void NullabilityOfTypeParameters_085() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0, T a0) { if (x0 == null) return; M3(M2(x0), a0); M3(M2(a0), x0); M3, object?>(z0, null); } I1 M2(U a) => throw null!; void M3(U a, W b) where U : I1 => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U, W)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3, object?>(z0, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3, object?>").WithArguments("Outer.M3(U, W)", "I1", "U", "I1").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_086() { var source = @" class Outer { void M0(T x0, I1 z0) where T : class? { if (x0 == null) return; M3(M2(x0)); M3(M2(x0)); M3>(M2(x0)); M3>(z0); } I1 M2(U a) => throw null!; void M3(U a) where U : I1 => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3(M2(x0)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3").WithArguments("Outer.M3(U)", "I1", "U", "I1").WithLocation(7, 9), // (8,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3(M2(x0)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3").WithArguments("Outer.M3(U)", "I1", "U", "I1").WithLocation(8, 9), // (9,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3>(M2(x0)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3>").WithArguments("Outer.M3(U)", "I1", "U", "I1").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_087() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0, U? a0) where T : class? where U : class, T { M3(M2(x0), a0); if (x0 == null) return; M3(M2(x0), a0); M3, U>(y0, null); M3, string>(z0, null); } I1 M2(U a) => throw null!; void M3(U a, W? b) where U : I1 where W : class => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_088() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0, U a0) where T : class? where U : class?, T { M3(M2(x0), a0); if (x0 == null) return; M3(M2(x0), a0); // 1 M3, U>(y0, a0); M3, string?>(z0, null); } I1 M2(U a) => throw null!; void M3(U a, W b) where U : I1 => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (12,9): warning CS8631: The type 'I1' cannot be used as type parameter 'U' in the generic type or method 'Outer.M3(U, W)'. Nullability of type argument 'I1' doesn't match constraint type 'I1'. // M3, string?>(z0, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M3, string?>").WithArguments("Outer.M3(U, W)", "I1", "U", "I1").WithLocation(12, 9) ); } [Fact] public void NullabilityOfTypeParameters_089() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0, T a0) { if (x0 == null) return; if (a0 == null) return; M3(M2(x0), a0); M3(M2(a0), x0); M3, object>(z0, new object()); } I1 M2(U a) => throw null!; void M3(U a, W b) where U : I1 => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_090() { var source = @" class Outer { void M0(T x0, I1 y0, I1 z0, T a0) { M3(M2(x0), a0); M3,T>(y0, a0); } I1 M2(U a) => throw null!; void M3(U a, W b) where U : I1 => throw null!; } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_091() { var source = @" class Outer { void M0(T x0) where T : I1? { x0?.ToString(); x0?.M1(x0); x0.ToString(); } } interface I1 { void M1(object x); } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // x0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_092() { var source = @" class Outer { void M0(T x0) { if (x0 is null) return; x0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_093() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = x0 ?? y0; M1(z0) = x0; M1(z0).ToString(); z0.ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_094() { var source = @" class Outer { void M0(T x0, T y0) { (x0 ?? y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (x0 ?? y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0 ?? y0").WithLocation(6, 10) ); } [Fact] [WorkItem(30952, "https://github.com/dotnet/roslyn/issues/30952")] public void NullabilityOfTypeParameters_095() { var source = @" class Outer { void M0(object? x0, T z0) { if (x0 is T y0) { M2(y0) = z0; x0.ToString(); y0.ToString(); } } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] [WorkItem(30952, "https://github.com/dotnet/roslyn/issues/30952")] public void NullabilityOfTypeParameters_096() { var source = @" class Outer { void M0(T x0, object? z0) { if (x0 is object y0) { M2(y0) = z0; x0.ToString(); y0.ToString(); } } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,22): warning CS8601: Possible null reference assignment. // M2(y0) = z0; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "z0").WithLocation(8, 22) ); } [Fact] public void NullabilityOfTypeParameters_097() { var source = @" class Outer { void M0(T x0, T z0) { if (x0 is var y0) { M2(y0) = z0; x0.ToString(); y0.ToString(); } } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,13): warning CS8602: Dereference of a possibly null reference. // x0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(9, 13), // (10,13): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(10, 13) ); } [Fact] public void NullabilityOfTypeParameters_098() { var source = @" class Outer { void M0(T x0) { if (x0 is default) return; x0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,19): error CS8505: A default literal 'default' is not valid as a pattern. Use another literal (e.g. '0' or 'null') as appropriate. To match everything, use a discard pattern '_'. // if (x0 is default) return; Diagnostic(ErrorCode.ERR_DefaultPattern, "default").WithLocation(6, 19), // (6,19): error CS0150: A constant value is expected // if (x0 is default) return; Diagnostic(ErrorCode.ERR_ConstantExpected, "default").WithLocation(6, 19), // (7,9): warning CS8602: Dereference of a possibly null reference. // x0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_099() { var source = @" class Outer { void M0(T x0) { if (x0 is default(T)) return; x0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,19): error CS0150: A constant value is expected // if (x0 is default(T)) return; Diagnostic(ErrorCode.ERR_ConstantExpected, "default(T)").WithLocation(6, 19), // (7,9): warning CS8602: Dereference of a possibly null reference. // x0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(7, 9) ); } [Fact] public void NullabilityOfTypeParameters_100() { var source = @" class Outer { void M0(T x0, T y0) where T : class? { if (x0 is null) return; M2(x0) = y0; M2(x0).ToString(); x0.ToString(); } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_101() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; (x0 ?? y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_102() { var source = @" class Outer { void M0(T x0, T y0) where T : class? { if (x0 == null) return; M2(x0) = y0; M2(x0).ToString(); x0.ToString(); } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(9, 9) ); } [Fact] [WorkItem(30952, "https://github.com/dotnet/roslyn/issues/30952")] public void NullabilityOfTypeParameters_103() { var source = @" class Outer { void M0(T x0, T z0) { if (x0 is T y0) { M2(x0) = z0; M2(y0) = z0; M2(x0).ToString(); M2(y0).ToString(); x0.ToString(); y0.ToString(); } } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,13): warning CS8602: Dereference of a possibly null reference. // M2(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(x0)").WithLocation(10, 13), // (11,13): warning CS8602: Dereference of a possibly null reference. // M2(y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(y0)").WithLocation(11, 13) ); } [Fact] public void NullabilityOfTypeParameters_104() { var source = @" class Outer { void M0(bool b, T x0) { T y0; if (b) { y0 = M2(); } else { y0 = x0; } y0.ToString(); } #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (17,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(17, 9) ); } [Fact] public void NullabilityOfTypeParameters_105() { var source = @" class Outer { void M0(bool b, T x0) { T y0; if (b) { y0 = x0; } else { y0 = M2(); } y0.ToString(); } #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (17,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(17, 9) ); } [Fact] public void NullabilityOfTypeParameters_106() { var source = @" class Outer { void M0(bool b, T x0) { T y0; if (b || x0 == null) { y0 = M3(); } else { y0 = x0; } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_107() { var source = @" class Outer { void M0(bool b, T x0) { T y0; if (b && x0 != null) { y0 = x0; } else { y0 = M3(); } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_108() { var source = @" class Outer { void M0(T x0) { x0!.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_109() { var source = @" class Outer { void M0(T x0) where T : I1 { x0 = default; } void M1(T x1) where T : I1 { x1 = default; } } interface I1 {} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (4,35): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // void M0(T x0) where T : I1 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(4, 35), // (6,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x0 = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(6, 14), // (11,14): warning CS8652: A default expression introduces a null value when 'T' is a non-nullable reference type. // x1 = default; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(11, 14) ); } [Fact] public void NullabilityOfTypeParameters_110() { var source = @" class Outer { void M0(T x0, T y0) { if (x0 == null) return; T z0 = x0 ?? y0; M1(z0).ToString(); M1(z0) = y0; z0.ToString(); z0?.ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(10, 9)); } [Fact] public void NullabilityOfTypeParameters_111() { var source = @" class Outer { void M0(T x0, T y0, T a0) { if (x0 == null) return; if (y0 == null) return; T z0 = x0 ?? y0; M1(z0) = a0; z0?.ToString(); M1(z0).ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_112() { var source = @" class Outer { void M0(T x0, T y0) { if (x0 == null) return; var z0 = x0; z0 = y0; } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_113() { var source = @" class Outer { void M0(T x0, T y0, T u0, T v0) { var a0 = new[] {x0, y0}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; M2(v0).ToString(); } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M2(v0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(v0)").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_114() { var source = @" class Outer { void M0(T x0, T y0, T u0, T v0) { if (x0 == null) return; var a0 = new[] {x0, y0}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; M2(v0) = a0[1]; M2(v0).ToString(); } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // M2(v0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(v0)").WithLocation(13, 9) ); } [Fact] public void NullabilityOfTypeParameters_115() { var source = @" class Outer { void M0(T x0, T y0, T u0, T v0) { if (y0 == null) return; var a0 = new[] {x0, y0}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; M2(v0) = a0[1]; M2(v0).ToString(); } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // M2(v0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(v0)").WithLocation(13, 9) ); } [Fact] public void NullabilityOfTypeParameters_116() { var source = @" class Outer { void M0(T x0, T y0, T u0, T v0) { if (x0 == null) return; if (y0 == null) return; var a0 = new[] {x0, y0}; a0[0] = u0; a0[0].ToString(); if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; } ref T M2(T x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // a0[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a0[0]").WithLocation(10, 9) ); } [Fact] public void NullabilityOfTypeParameters_117() { var source = @" class Outer { void M0(T x0, T u0, T v0) { var a0 = new[] {x0, M3()}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_118() { var source = @" class Outer { void M0(T x0, T u0, T v0) { var a0 = new[] {M3(), x0}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_119() { var source = @" class Outer { void M0(T x0, T u0, T v0) { if (x0 == null) return; var a0 = new[] {x0, M3()}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_120() { var source = @" class Outer { void M0(T x0, T u0, T v0) { if (x0 == null) return; var a0 = new[] {M3(), x0}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_121() { var source = @" class Outer { void M0(T u0, T v0) { var a0 = new[] {M3(), M3()}; a0[0] = u0; if (v0 == null) return; a0[0] = v0; M2(v0) = a0[1]; } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_122() { var source = @" class Outer { void M0(bool b, T x0) { T y0; if (b) { y0 = M3(); } else { y0 = M3(); } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; #nullable disable T M3() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_123() { var source = @" class Outer { void M0(bool b, T x0, T a0, T b0) { if (a0 == null) return; if (b0 == null) return; T y0; if (b) { y0 = a0; } else { y0 = b0; } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_124() { var source = @" class Outer { void M0(bool b, T x0, T a0, T b0) { T y0; if (b) { y0 = a0; } else { y0 = b0; } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (18,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(18, 9) ); } [Fact] public void NullabilityOfTypeParameters_125() { var source = @" class Outer { void M0(bool b, T x0, T a0, T b0) { if (a0 == null) return; T y0; if (b) { y0 = a0; } else { y0 = b0; } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (20,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(20, 9) ); } [Fact] public void NullabilityOfTypeParameters_126() { var source = @" class Outer { void M0(bool b, T x0, T a0, T b0) { if (b0 == null) return; T y0; if (b) { y0 = a0; } else { y0 = b0; } M2(y0) = x0; y0.ToString(); } ref T M2(U x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (20,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(20, 9) ); } [Fact] public void NullabilityOfTypeParameters_127() { var source = @" class C { public C X = null!; public C Y = null!; void F(object? y0) { if (y0 == null) return; object? x0; x0 = null; _ = new C() { Y = M(x0), X = M(y0) }; } ref C M(S x) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_128() { var source = @" class C { void F(object? y0) { if (y0 == null) return; object? x0; x0 = null; M2( out M1(x0), out M1(y0) ); } ref C M1(S x) => throw null!; void M2(out C x, out C y) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_129() { var source = @" class C { void F(object? y0) { if (y0 == null) return; object? x0; x0 = null; M2( ref M1(x0), ref M1(y0) ); } ref C M1(S x) => throw null!; void M2(ref C x, ref C y) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_130() { var source = @" class C { void F(object? y0) { if (y0 == null) return; object? x0; x0 = null; M2(M1(x0), M1(y0)) = (C a, C b) => throw null!; } C M1(S x) => throw null!; ref System.Action M2(U x, V y) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_131() { var source = @" class C where T : class? { void F(T y0) { if (y0 == null) return; T x0; x0 = null; M2(M1(x0), M1(y0)) = (C a, C b) => throw null!; } C M1(S x) where S : class? => throw null!; ref System.Action M2(U x, V y) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8654: A null literal introduces a null value when 'T' is a non-nullable reference type. // x0 = null; Diagnostic(ErrorCode.WRN_NullLiteralMayIntroduceNullT, "null").WithArguments("T").WithLocation(8, 14)); } [Fact] public void NullabilityOfTypeParameters_132() { var source = @" class C where T : class? { void F(T x0, T y0) { M2(M1(x0), M1(y0)) = (C a, C b) => throw null!; } C M1(S x) where S : class? => throw null!; ref System.Action M2(U x, V y) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_133() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = M2() ?? y0; M1(z0) = x0; M1(z0) = x0; M1(z0).ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_134() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = y0 ?? M2(); M1(z0) = x0; M1(z0) = x0; M1(z0).ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_135() { var source = @" class Outer { void M0(T x0) { T z0 = M2() ?? M2(); M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_136() { var source = @" class Outer { void M0(T x0, T y0) { T z0 = M2() ?? y0; M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9)); } [Fact] public void NullabilityOfTypeParameters_137() { var source = @" class Outer { void M0(T x0, T y0) { T z0 = y0 ?? M2(); M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_138() { var source = @" class C where T : class? { void F(T x0, T y0) { T z0 = x0 ?? y0; M2(M1(z0)) = (C a) => throw null!; } C M1(S x) where S : class? => throw null!; ref System.Action M2(U x) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_139() { var source = @" class C where T : class? { void F(T x0, T y0) { T z0 = x0 ?? y0; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_140() { var source = @" class C where T : class? { void F(T x0, T y0) { T z0 = new [] {x0, y0}[0]; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_141() { var source = @" struct C where T : class? { void F(T x0, object? y0) { F1 = x0; F2 = y0; x0 = F1; y0 = F2; } #nullable disable T F1; object F2; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_142() { var source = @" class Outer { void M0(bool b, T x0, T y0) { (b ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (b ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x0 : y0").WithLocation(6, 10) ); } [Fact] public void NullabilityOfTypeParameters_143() { var source = @" class Outer { void M0(bool b, T x0, T y0) { if (y0 == null) return; (b ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,10): warning CS8602: Dereference of a possibly null reference. // (b ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x0 : y0").WithLocation(7, 10) ); } [Fact] public void NullabilityOfTypeParameters_144() { var source = @" class Outer { void M0(bool b, T x0, T y0) { if (x0 == null) return; (b ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,10): warning CS8602: Dereference of a possibly null reference. // (b ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b ? x0 : y0").WithLocation(7, 10) ); } [Fact] public void NullabilityOfTypeParameters_145() { var source = @" class Outer { void M0(bool b, T x0, T y0, T a0) { if (x0 == null) return; if (y0 == null) return; T z0 = b ? x0 : y0; M1(z0) = a0; z0?.ToString(); M1(z0).ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(11, 9) ); } [Fact, WorkItem(33924, "https://github.com/dotnet/roslyn/issues/33924")] public void NullabilityOfTypeParameters_146() { var source = @" class Outer { void M0(bool b, T x0, T y0) { if (y0 == null) return; T z0 = b ? M2() : y0; M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact, WorkItem(33924, "https://github.com/dotnet/roslyn/issues/33924")] public void NullabilityOfTypeParameters_147() { var source = @" class Outer { void M0(bool b, T x0, T y0) { if (y0 == null) return; T z0 = b ? y0 : M2(); M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact, WorkItem(33924, "https://github.com/dotnet/roslyn/issues/33924")] public void NullabilityOfTypeParameters_148() { var source = @" class Outer { void M0(bool b, T x0) { T z0 = b ? M2() : M2(); M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_149() { var source = @" class Outer { void M0(bool b, T x0, T y0) { T z0 = b ? M2() : y0; M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_150() { var source = @" class Outer { void M0(bool b, T x0, T y0) { T z0 = b ? y0 : M2(); M1(z0) = x0; z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_151() { var source = @" class C where T : class? { void F(bool b, T x0, T y0) { T z0 = b ? x0 : y0; M2(M1(z0)) = (C a) => throw null!; } C M1(S x) where S : class? => throw null!; ref System.Action M2(U x) => throw null!; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_153() { var source = @" class Outer { void M0(T x0, T y0) { (true ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (true ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "true ? x0 : y0").WithLocation(6, 10) ); } [Fact] public void NullabilityOfTypeParameters_154() { var source = @" class Outer { void M0(bool b, T x0, T y0) { if (y0 == null) return; (true ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,10): warning CS8602: Dereference of a possibly null reference. // (true ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "true ? x0 : y0").WithLocation(7, 10) ); } [Fact, WorkItem(33924, "https://github.com/dotnet/roslyn/issues/33924")] public void NullabilityOfTypeParameters_155() { var source = @" class Outer { void M0(T x0, T y0) { if (x0 == null) return; (true ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_156() { var source = @" class Outer { void M0(T x0, T y0, T a0) { if (x0 == null) return; if (y0 == null) return; T z0 = true ? x0 : y0; M1(z0) = a0; M1(z0).ToString(); z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(12, 9)); } [Fact] public void NullabilityOfTypeParameters_157() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = true ? M2() : y0; M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(10, 9)); } [Fact] public void NullabilityOfTypeParameters_158() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = true ? y0 : M2(); M1(z0) = x0; M1(z0).ToString(); z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9)); } [Fact] public void NullabilityOfTypeParameters_159() { var source = @" class Outer { void M0(T x0) { T z0 = true ? M2() : M2(); M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_160() { var source = @" class Outer { void M0(T x0, T y0) { T z0 = true ? M2() : y0; M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_161() { var source = @" class Outer { void M0(T x0, T y0) { T z0 = true ? y0 : M2(); M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_162() { var source = @" class Outer { void M0(T x0, T y0) { (false ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (false ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "false ? x0 : y0").WithLocation(6, 10) ); } [Fact, WorkItem(33924, "https://github.com/dotnet/roslyn/issues/33924")] public void NullabilityOfTypeParameters_163() { var source = @" class Outer { void M0(bool b, T x0, T y0) { if (y0 == null) return; (false ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_164() { var source = @" class Outer { void M0(T x0, T y0) { if (x0 == null) return; (false ? x0 : y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,10): warning CS8602: Dereference of a possibly null reference. // (false ? x0 : y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "false ? x0 : y0").WithLocation(7, 10) ); } [Fact] public void NullabilityOfTypeParameters_165() { var source = @" class Outer { void M0(T x0, T y0, T a0) { if (x0 == null) return; if (y0 == null) return; T z0 = false ? x0 : y0; M1(z0) = a0; M1(z0).ToString(); z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(12, 9)); } [Fact] public void NullabilityOfTypeParameters_166() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = false ? M2() : y0; M1(z0) = x0; M1(z0).ToString(); z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9)); } [Fact] public void NullabilityOfTypeParameters_167() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; T z0 = false ? y0 : M2(); M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(10, 9)); } [Fact] public void NullabilityOfTypeParameters_168() { var source = @" class Outer { void M0(T x0) { T z0 = false ? M2() : M2(); M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_169() { var source = @" class Outer { void M0(T x0, T y0) { T z0 = false ? M2() : y0; M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_170() { var source = @" class Outer { void M0(T x0, T y0) { T z0 = false ? y0 : M2(); M1(z0) = x0; z0?.ToString(); z0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9)); } [Fact] public void NullabilityOfTypeParameters_171() { var source = @" class Outer where T : Outer? where U : T { void M0(T x0) { U y0 = (U)x0; U z0 = y0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8601: Possible null reference assignment. // U y0 = (U)x0; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x0").WithLocation(6, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_172() { var source = @" class Outer where T : class? where U : T { void M0(T x0) { U y0 = (U)x0; U z0 = y0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8601: Possible null reference assignment. // U y0 = (U)x0; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)x0").WithLocation(6, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9)); } [Fact] public void NullabilityOfTypeParameters_173() { var source = @" class Outer where T : Outer?, U { void M0(T x0) { T z0 = x0?.M1(); U y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_174() { var source = @" class Outer where T : Outer? where U : T { void M0(T x0) { T z0 = x0?.M1(); U y0 = (U)z0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (7,16): warning CS8601: Possible null reference assignment. // U y0 = (U)z0; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(U)z0").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_175() { var source = @" class Outer where T : Outer?, U { void M0(T x0) { if (x0 == null) return; T z0 = x0?.M1(); U y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(7, 16), // (10,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(12, 9) ); } [Fact] public void NullabilityOfTypeParameters_176() { var source = @" class Outer where T : Outer?, U { void M0(Outer? x0) { T z0 = x0?.M1(); U y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_177() { var source = @" class Outer where T : Outer?, U { void M0(Outer x0) { T z0 = x0?.M1(); U y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9) ); } [Fact] public void NullabilityOfTypeParameters_178() { var source = @" class Outer where T : Outer? { void M0(T x0) { Outer z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } Outer M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(6, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_179() { var source = @" class Outer where T : Outer? { void M0(T x0) { if (x0 == null) return; Outer z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } Outer M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(7, 23), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_180() { var source = @" class Outer where T : Outer? { void M0(T x0) { Outer z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } Outer? M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(6, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_181() { var source = @" class Outer where T : Outer? { void M0(T x0) { if (x0 == null) return; Outer z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } Outer? M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(7, 23), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_182() { var source = @" class Outer where T : Outer?, U where U : class? { void M0(T x0) { U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } U M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_183() { var source = @" class Outer where T : Outer?, U where U : class? { void M0(T x0) { if (x0 == null) return; U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } U M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_184() { var source = @" class Outer where T : U where U : Outer? { void M0(U x0) { U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_185() { var source = @" class Outer where T : U where U : Outer? { void M0(U x0) { T z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_186() { var source = @" class Outer where T : U where U : Outer? { void M0(U x0) { if (x0 == null) return; U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_187() { var source = @" class Outer where T : U where U : Outer? { void M0(U x0) { if (x0 == null) return; T z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } T M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8638: Conditional access may produce a null value when 'T' is a non-nullable reference type. // T z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_188() { var source = @" class Outer where T : Outer? where U : class? { void M0(T x0) { U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } U M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_189() { var source = @" class Outer where T : Outer? where U : class? { void M0(T x0) { if (x0 == null) return; U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } U M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8638: Conditional access may produce a null value when 'U' is a non-nullable reference type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConditionalAccessMayReturnNull, "x0?.M1()").WithArguments("U").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_190() { var source = @" class Outer where T : Outer? where U : class { void M0(T x0) { U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } U M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_191() { var source = @" class Outer where T : Outer? where U : class { void M0(T x0) { if (x0 == null) return; U z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } U M1() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // U z0 = x0?.M1(); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0?.M1()").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // z0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_192() { var source = @" class Outer { void M0(T x0) { object y0 = x0 as object; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y0 = x0 as object; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as object").WithLocation(6, 21), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_193() { var source = @" class Outer { void M0(T x0) { if (x0 == null) return; object y0 = x0 as object; y0?.ToString(); y0.ToString(); // 1 } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_194() { var source = @" class Outer { void M0(T x0) { dynamic y0 = x0 as dynamic; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // dynamic y0 = x0 as dynamic; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as dynamic").WithLocation(6, 22), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_195() { var source = @" class Outer { void M0(T x0) { if (x0 == null) return; dynamic y0 = x0 as dynamic; y0?.ToString(); y0.ToString(); // 1 } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_196() { var source = @" class Outer where T : class? { void M0(object x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_197() { var source = @" class Outer where T : class? { void M0(object? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_198() { var source = @" class Outer where T : class? { void M0(object? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_199() { var source = @" class Outer where T : class? { void M0(dynamic x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_200() { var source = @" class Outer where T : class? { void M0(dynamic? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_201() { var source = @" class Outer where T : class? { void M0(dynamic? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_202() { var source = @" class Outer where T : notnull { void M0(T x0) { object y0 = x0 as object; y0?.ToString(); y0.ToString(); // 1 } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_203() { var source = @" class Outer where T : notnull { void M0(T x0) { dynamic y0 = x0 as dynamic; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_204() { var source = @" class Outer where T : class { void M0(object x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_205() { var source = @" class Outer where T : class { void M0(object? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_206() { var source = @" class Outer where T : class { void M0(object? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_207() { var source = @" class Outer where T : class { void M0(dynamic x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_208() { var source = @" class Outer where T : class { void M0(dynamic? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_209() { var source = @" class Outer where T : class { void M0(dynamic? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_210() { var source = @" class Outer { void M0(T x0) { Outer y0 = x0 as Outer; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer y0 = x0 as Outer; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as Outer").WithLocation(6, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_211() { var source = @" class Outer { void M0(T x0) { if (x0 == null) return; Outer y0 = x0 as Outer; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer y0 = x0 as Outer; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as Outer").WithLocation(7, 23), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_212() { var source = @" class Outer where T : class? { void M0(Outer? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_213() { var source = @" class Outer where T : class? { void M0(Outer? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_214() { var source = @" class Outer where T : class? { void M0(Outer x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_215() { var source = @" class Outer where T : class { void M0(T x0) { Outer y0 = x0 as Outer; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer y0 = x0 as Outer; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as Outer").WithLocation(6, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_216() { var source = @" class Outer where T : class { void M0(Outer? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_217() { var source = @" class Outer where T : class { void M0(Outer? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_218() { var source = @" class Outer where T : class { void M0(Outer x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_219() { var source = @" class Outer where T : Outer? { void M0(T x0) { Outer y0 = x0 as Outer; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // Outer y0 = x0 as Outer; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as Outer").WithLocation(6, 23), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_220() { var source = @" class Outer where T : Outer? { void M0(T x0) { if (x0 == null) return; Outer y0 = x0 as Outer; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_221() { var source = @" class Outer where T : Outer? { void M0(Outer x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_222() { var source = @" class Outer where T : Outer { void M0(T x0) { Outer y0 = x0 as Outer; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_223() { var source = @" class Outer where T : Outer { void M0(Outer? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_224() { var source = @" class Outer where T : Outer { void M0(Outer? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_225() { var source = @" class Outer where T : Outer { void M0(Outer x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_226() { var source = @" class Outer where T : I1? { void M0(T x0) { I1 y0 = x0 as I1; y0?.ToString(); y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // I1 y0 = x0 as I1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as I1").WithLocation(6, 17), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_227() { var source = @" class Outer where T : I1? { void M0(T x0) { if (x0 == null) return; I1 y0 = x0 as I1; y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_228() { var source = @" class Outer where T : class?, I1? { void M0(I1 x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_229() { var source = @" class Outer where T : I1 { void M0(T x0) { I1 y0 = x0 as I1; y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_230() { var source = @" class Outer where T : class?, I1 { void M0(I1? x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_231() { var source = @" class Outer where T : class?, I1 { void M0(I1? x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_232() { var source = @" class Outer where T : class?, I1 { void M0(I1 x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } interface I1{} "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_233() { var source = @" class Outer where T : class? { void M0(T x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_234() { var source = @" class Outer where T : class? { void M0(T x0) { if (x0 == null) return; T y0 = x0 as T; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_235() { var source = @" class Outer where T : class { void M0(T x0) { T y0 = x0 as T; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_237() { var source = @" class Outer where T : U where U : class? { void M0(T x0) { U y0 = x0 as U; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_238() { var source = @" class Outer where T : U where U : class? { void M0(T x0) { if (x0 == null) return; U y0 = x0 as U; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_239() { var source = @" class Outer where T : U where U : class { void M0(T x0) { U y0 = x0 as U; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_240() { var source = @" class Outer where T : class, U where U : class? { void M0(T x0) { U y0 = x0 as U; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_241() { var source = @" class Outer where T : class?, U where U : class? { void M0(T x0) { U y0 = x0 as U; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_242() { var source = @" class Outer where T : class?, U where U : class? { void M0(T x0) { if (x0 == null) return; U y0 = x0 as U; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_243() { var source = @" class Outer where T : class?, U where U : class { void M0(T x0) { U y0 = x0 as U; y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_244() { var source = @" class Outer where T : class, U where U : class? { void M0(U x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_245() { var source = @" class Outer where T : class, U where U : class? { void M0(U x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_246() { var source = @" class Outer where T : class, U where U : class { void M0(U x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_248() { var source = @" class Outer where T : class?, U where U : class? { void M0(U x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_249() { var source = @" class Outer where T : class?, U where U : class? { void M0(U x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_250() { var source = @" class Outer where T : class?, U where U : class { void M0(U x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_251() { var source = @" class Outer where T : class?, U { void M0(U x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_252() { var source = @" class Outer where T : class?, U { void M0(U x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8626: The 'as' operator may produce a null value when 'T' is a non-nullable reference type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_AsOperatorMayReturnNull, "x0 as T").WithArguments("T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_253() { var source = @" class Outer where T : class, U { void M0(U x0) { T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(6, 16), // (8,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ); } [Fact] public void NullabilityOfTypeParameters_254() { var source = @" class Outer where T : class, U { void M0(U x0) { if (x0 == null) return; T y0 = x0 as T; y0?.ToString(); y0.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y0 = x0 as T; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x0 as T").WithLocation(7, 16), // (9,9): warning CS8602: Dereference of a possibly null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ); } [Fact] public void NullabilityOfTypeParameters_255() { var source = @" class Outer { void M0(T x0, T y0, T z0) { if (y0 == null) return; z0 ??= y0; M1(z0) = x0; M1(z0).ToString(); z0.ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // M1(z0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(z0)").WithLocation(10, 9)); } [Fact] public void NullabilityOfTypeParameters_256() { var source = @" class Outer { void M0(T x0, T y0) { (x0 ??= y0).ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // (x0 ??= y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0 ??= y0").WithLocation(6, 10)); } [Fact] public void NullabilityOfTypeParameters_257() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; (x0 ??= y0)?.ToString(); } } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( ); } [Fact] public void NullabilityOfTypeParameters_258() { var source = @" class Outer { void M0(T x0, T y0) { if (x0 == null) return; x0 ??= y0; M1(x0).ToString(); M1(x0) = y0; x0?.ToString(); x0.ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // M1(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x0)").WithLocation(8, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // x0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(11, 9)); } [Fact] public void NullabilityOfTypeParameters_259() { var source = @" class Outer { void M0(T x0, T y0, T a0) { if (x0 == null) return; if (y0 == null) return; x0 ??= y0; M1(x0) = a0; x0?.ToString(); M1(x0).ToString(); } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M1(x0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(x0)").WithLocation(11, 9)); } [Fact] public void NullabilityOfTypeParameters_260() { var source = @" class Outer { void M0(T x0, T y0) { if (y0 == null) return; y0 ??= M2(); M1(y0) = x0; M1(y0) = x0; M1(y0).ToString(); y0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // M1(y0).ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M1(y0)").WithLocation(11, 9)); } [Fact] public void NullabilityOfTypeParameters_261() { var source = @" class Outer { void M0(T x0, T y0) { y0 ??= M2(); M1(y0) = x0; y0.ToString(); } ref S M1(S x) => throw null!; #nullable disable T M2() => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void NullabilityOfTypeParameters_262() { var source = @" class Outer where T1 : class, T2 { void M0(T1 t1, T2 t2) { t1 ??= t2 as T1; M1(t1) ??= t2 as T1; } ref S M1(S x) => throw null!; } "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( // (6,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // t1 ??= t2 as T1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t2 as T1").WithLocation(6, 16)); } [Fact] public void UpdateFieldFromReceiverType() { var source = @"class A { } class B { internal T F = default!; } class Program { internal static B Create(T t) => throw null!; static void M1(object x, object? y) { var b1 = Create(x); b1.F = x; b1.F = y; // 1 } static void M2(A x, A y, A z) { var b2 = Create(x); b2.F = y; // 2 b2.F = z; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,16): warning CS8601: Possible null reference assignment. // b1.F = y; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(13, 16), // (18,16): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // b2.F = y; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "A").WithLocation(18, 16)); } [Fact] public void UpdatePropertyFromReceiverType() { var source = @"class A { } class B { internal T P { get; set; } = default!; } class Program { internal static B Create(T t) => throw null!; static void M1(object x, object? y) { var b1 = Create(x); b1.P = x; b1.P = y; // 1 } static void M2(A x, A y, A z) { var b2 = Create(x); b2.P = y; // 2 b2.P = z; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,16): warning CS8601: Possible null reference assignment. // b1.P = y; // 1 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "y").WithLocation(13, 16), // (18,16): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // b2.P = y; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("A", "A").WithLocation(18, 16)); } [WorkItem(31018, "https://github.com/dotnet/roslyn/issues/31018")] [Fact] public void UpdateEventFromReceiverType() { var source = @"#pragma warning disable 0067 delegate void D(T t); class C { internal event D E; } class Program { internal static C Create(T t) => throw null!; static void M1(object x, D y, D z) { var c1 = Create(x); c1.E += y; c1.E += z; // 1 } static void M2(object? x, D y, D z) { var c2 = Create(x); c2.E += y; // 2 c2.E += z; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/31018: Report warnings. comp.VerifyDiagnostics(); } [WorkItem(29605, "https://github.com/dotnet/roslyn/issues/29605")] [Fact] public void UpdateMethodFromReceiverType_01() { var source = @"class C { internal void F(T t) { } } class Program { internal static C Create(T t) => throw null!; static void M(object x, object? y, string? z) { var c = Create(x); c.F(x); c.F(y); // 1 c.F(z); // 2 c.F(null); // 3 } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F(object t)'. // c.F(y); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "void C.F(object t)").WithLocation(12, 13), // (13,13): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F(object t)'. // c.F(z); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "z").WithArguments("t", "void C.F(object t)").WithLocation(13, 13), // (14,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // c.F(null); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(14, 13)); } [WorkItem(29605, "https://github.com/dotnet/roslyn/issues/29605")] [Fact] public void UpdateMethodFromReceiverType_02() { var source = @"class A { } class B { internal void F(U u) where U : A { } } class Program { internal static B Create(T t) => throw null!; static void M1(object x, A y, A z) { var b1 = Create(x); b1.F(y); b1.F(z); // 1 } static void M2(object? x, A y, A z) { var b2 = Create(x); b2.F(y); // 2 b2.F(z); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8631: The type 'A' cannot be used as type parameter 'U' in the generic type or method 'B.F(U)'. Nullability of type argument 'A' doesn't match constraint type 'A'. // b1.F(z); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "b1.F").WithArguments("B.F(U)", "A", "U", "A").WithLocation(13, 9), // (18,9): warning CS8631: The type 'A' cannot be used as type parameter 'U' in the generic type or method 'B.F(U)'. Nullability of type argument 'A' doesn't match constraint type 'A'. // b2.F(y); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "b2.F").WithArguments("B.F(U)", "A", "U", "A").WithLocation(18, 9)); } [WorkItem(29605, "https://github.com/dotnet/roslyn/issues/29605")] [Fact] public void UpdateMethodFromReceiverType_03() { var source = @"class C { internal static T F() => throw null!; } class Program { internal static C Create(T t) => throw null!; static void M(object x) { var c1 = Create(x); c1.F().ToString(); x = null; var c2 = Create(x); c2.F().ToString(); } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): error CS0176: Member 'C.F()' cannot be accessed with an instance reference; qualify it with a type name instead // c1.F().ToString(); Diagnostic(ErrorCode.ERR_ObjectProhibited, "c1.F").WithArguments("C.F()").WithLocation(11, 9), // (12,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 13), // (14,9): error CS0176: Member 'C.F()' cannot be accessed with an instance reference; qualify it with a type name instead // c2.F().ToString(); Diagnostic(ErrorCode.ERR_ObjectProhibited, "c2.F").WithArguments("C.F()").WithLocation(14, 9)); } [Fact] public void AnnotationsInMetadata_01() { var source = @" using System.Collections.Generic; class B { public int F01; public int? F02; public string F03; public string? F04; public KeyValuePair F05; public KeyValuePair F06; public KeyValuePair F07; public KeyValuePair F08; public KeyValuePair F09; public KeyValuePair F10; public KeyValuePair F11; public KeyValuePair F12; public KeyValuePair F13; public Dictionary F14; public Dictionary? F15; public Dictionary F16; public Dictionary? F17; public Dictionary F18; public Dictionary? F19; public Dictionary F20; public Dictionary? F21; public Dictionary F22; public Dictionary? F23; public Dictionary F24; public Dictionary? F25; public Dictionary F26; public Dictionary? F27; public Dictionary F28; public Dictionary? F29; public Dictionary F30; public Dictionary? F31; } "; var comp = CreateCompilation(new[] { source }); CompileAndVerify(comp, symbolValidator: validateAnnotationsContextFalse); comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(NullableContextOptions.Warnings)); CompileAndVerify(comp, symbolValidator: validateAnnotationsContextFalse); comp = CreateCompilation(new[] { @"#nullable enable warnings " + source }); CompileAndVerify(comp, symbolValidator: validateAnnotationsContextFalse); comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); CompileAndVerify(comp, symbolValidator: validateAnnotationsContextTrue); comp = CreateCompilation(new[] { source }, options: WithNonNullTypes(NullableContextOptions.Annotations)); CompileAndVerify(comp, symbolValidator: validateAnnotationsContextTrue); comp = CreateCompilation(new[] { @"#nullable enable annotations " + source }); CompileAndVerify(comp, symbolValidator: validateAnnotationsContextTrue); static void validateAnnotationsContextFalse(ModuleSymbol m) { (string type, string attribute)[] baseline = new[] { ("System.Int32", null), ("System.Int32?", null), ("System.String", null), ("System.String?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.KeyValuePair", null), ("System.Collections.Generic.KeyValuePair", null), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2, 0})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 0, 2})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2, 2})"), ("System.Collections.Generic.KeyValuePair", null), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2})"), ("System.Collections.Generic.KeyValuePair", null), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2})"), ("System.Collections.Generic.Dictionary", null), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.Dictionary", null), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 0, 0})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 2, 0})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 2, 0})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 0, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 0, 2})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 2, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.Dictionary", null), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 0})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.Dictionary", null), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 0})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)") }; Assert.Equal(31, baseline.Length); AnnotationsInMetadataFieldSymbolValidator(m, baseline); } static void validateAnnotationsContextTrue(ModuleSymbol m) { (string type, string attribute)[] baseline = new[] { ("System.Int32", null), ("System.Int32?", null), ("System.String!", "System.Runtime.CompilerServices.NullableAttribute(1)"), ("System.String?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.KeyValuePair", null), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 1, 1})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2, 1})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 1, 2})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2, 2})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 1})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 1})"), ("System.Collections.Generic.KeyValuePair", "System.Runtime.CompilerServices.NullableAttribute({0, 2})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute(1)"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute(1)"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 1, 1})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 2, 1})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 2, 1})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 1, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 1, 2})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 2, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute(1)"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 1})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute(1)"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 1})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 2})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute(2)") }; } } private static void AnnotationsInMetadataFieldSymbolValidator(ModuleSymbol m, (string type, string attribute)[] baseline) { var b = m.GlobalNamespace.GetMember("B"); for (int i = 0; i < baseline.Length; i++) { var name = "F" + (i + 1).ToString("00"); var f = b.GetMember(name); Assert.Equal(baseline[i].type, f.TypeWithAnnotations.ToTestDisplayString(true)); if (baseline[i].attribute == null) { Assert.Empty(f.GetAttributes()); } else { Assert.Equal(baseline[i].attribute, f.GetAttributes().Single().ToString()); } } } [Fact] public void AnnotationsInMetadata_02() { var ilSource = @" // =============== CLASS MEMBERS DECLARATION =================== .class private auto ansi beforefieldinit B`12 extends [mscorlib]System.Object { .param type T01 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) .param type T02 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) .param type T03 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .param type T04 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 03 00 00 ) .param type T05 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 04 00 00 ) .param type T06 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 05 00 00 ) .param type T07 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 00 00 00 ) .param type T08 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 01 00 00 ) .param type T09 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 02 00 00 ) .param type T10 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 01 00 00 ) .param type T11 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 00 00 00 00 00 00 ) .param type T12 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 FF FF FF FF 00 00 ) .field public int32 F01 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) .field public int32 F02 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 ) .field public int32 F03 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 ) .field public int32 F04 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 03 00 00 ) .field public int32 F05 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 00 00 00 ) .field public int32 F06 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 01 00 00 ) .field public int32 F07 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 02 00 00 ) .field public int32 F08 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 04 00 00 ) .field public int32 F09 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 FF FF FF FF 00 00 ) .field public valuetype [mscorlib]System.Nullable`1 F10 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) .field public valuetype [mscorlib]System.Nullable`1 F11 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 00 00 00 00 ) .field public valuetype [mscorlib]System.Nullable`1 F12 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 FF FF FF FF 00 00 ) .field public string F13 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) .field public string F14 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 03 00 00 ) .field public string F15 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 00 00 00 ) .field public string F16 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 01 00 00 ) .field public string F17 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 02 00 00 ) .field public string F18 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 01 00 00 00 04 00 00 ) .field public string F19 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 FF FF FF FF 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F20 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 00 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F21 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 03 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F22 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 FF FF FF FF 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F23 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 00 00 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F24 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 01 01 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F25 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 02 02 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F26 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 04 05 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F27 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 01 02 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F28 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 01 02 00 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F29 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 02 00 01 00 00 ) .field public string F30 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 01 00 00 ) .field public string F31 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 00 00 00 00 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F32 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 04 00 00 00 01 01 01 01 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F33 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 02 00 00 00 01 01 00 00 ) .field public class [mscorlib]System.Collections.Generic.Dictionary`2 F34 .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 00 00 00 00 00 00 ) .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method B`12::.ctor } // end of class B`12 .class public auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute extends [mscorlib]System.Attribute { .method public hidebysig specialname rtspecialname instance void .ctor(uint8 x) cil managed { // Code size 9 (0x9) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret } // end of method NullableAttribute::.ctor .method public hidebysig specialname rtspecialname instance void .ctor(uint8[] x) cil managed { // Code size 9 (0x9) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret } // end of method NullableAttribute::.ctor } // end of class System.Runtime.CompilerServices.NullableAttribute // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** /* class B<[Nullable(0)]T01, [Nullable(1)]T02, [Nullable(2)]T03, [Nullable(3)]T04, [Nullable(4)]T05, [Nullable(5)]T06, [Nullable(new byte[] { 0 })]T07, [Nullable(new byte[] { 1 })]T08, [Nullable(new byte[] { 2 })]T09, [Nullable(new byte[] { 1, 1 })]T10, [Nullable(new byte[] { })]T11, [Nullable(null)]T12> where T01 : class where T02 : class where T03 : class where T04 : class where T05 : class where T06 : class where T07 : class where T08 : class where T09 : class where T10 : class where T11 : class where T12 : class { [Nullable(0)] public int F01; [Nullable(1)] public int F02; [Nullable(2)] public int F03; [Nullable(3)] public int F04; [Nullable(new byte[] { 0 })] public int F05; [Nullable(new byte[] { 1 })] public int F06; [Nullable(new byte[] { 2 })] public int F07; [Nullable(new byte[] { 4 })] public int F08; [Nullable(null)] public int F09; [Nullable(0)] public int? F10; [Nullable(new byte[] { 0, 0 })] public int? F11; [Nullable(null)] public int? F12; [Nullable(0)] public string F13; [Nullable(3)] public string F14; [Nullable(new byte[] { 0 })] public string F15; [Nullable(new byte[] { 1 })] public string F16; [Nullable(new byte[] { 2 })] public string F17; [Nullable(new byte[] { 4 })] public string F18; [Nullable(null)] public string F19; [Nullable(0)] public System.Collections.Generic.Dictionary F20; [Nullable(3)] public System.Collections.Generic.Dictionary F21; [Nullable(null)] public System.Collections.Generic.Dictionary F22; [Nullable(new byte[] { 0, 0, 0 })] public System.Collections.Generic.Dictionary F23; [Nullable(new byte[] { 1, 1, 1 })] public System.Collections.Generic.Dictionary F24; [Nullable(new byte[] { 2, 2, 2 })] public System.Collections.Generic.Dictionary F25; [Nullable(new byte[] { 1, 4, 5 })] public System.Collections.Generic.Dictionary F26; [Nullable(new byte[] { 0, 1, 2 })] public System.Collections.Generic.Dictionary F27; [Nullable(new byte[] { 1, 2, 0 })] public System.Collections.Generic.Dictionary F28; [Nullable(new byte[] { 2, 0, 1 })] public System.Collections.Generic.Dictionary F29; [Nullable(new byte[] { 1, 1 })] public string F30; [Nullable(new byte[] { })] public string F31; [Nullable(new byte[] { 1, 1, 1, 1 })] public System.Collections.Generic.Dictionary F32; [Nullable(new byte[] { 1, 1 })] public System.Collections.Generic.Dictionary F33; [Nullable(new byte[] { })] public System.Collections.Generic.Dictionary F34; }*/ "; var source = @""; var compilation = CreateCompilation(new[] { source }, new[] { CompileIL(ilSource) }); NamedTypeSymbol b = compilation.GetTypeByMetadataName("B`12"); (string type, string attribute)[] fieldsBaseline = new[] { ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute(0)"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute(1)"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute(2)"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute(3)"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute({0})"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute({1})"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute({2})"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute({4})"), ("System.Int32", "System.Runtime.CompilerServices.NullableAttribute(null)"), ("System.Int32?", "System.Runtime.CompilerServices.NullableAttribute(0)"), ("System.Int32?", "System.Runtime.CompilerServices.NullableAttribute({0, 0})"), ("System.Int32?", "System.Runtime.CompilerServices.NullableAttribute(null)"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute(0)"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute(3)"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute({0})"), ("System.String!", "System.Runtime.CompilerServices.NullableAttribute({1})"), ("System.String?", "System.Runtime.CompilerServices.NullableAttribute({2})"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute({4})"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute(null)"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute(0)"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute(3)"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute(null)"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 0, 0})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 1, 1})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 2, 2})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({1, 4, 5})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({0, 1, 2})"), ("System.Collections.Generic.Dictionary!", "System.Runtime.CompilerServices.NullableAttribute({1, 2, 0})"), ("System.Collections.Generic.Dictionary?", "System.Runtime.CompilerServices.NullableAttribute({2, 0, 1})"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute({1, 1})"), ("System.String", "System.Runtime.CompilerServices.NullableAttribute({})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({1, 1, 1, 1})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({1, 1})"), ("System.Collections.Generic.Dictionary", "System.Runtime.CompilerServices.NullableAttribute({})"), }; Assert.Equal(34, fieldsBaseline.Length); AnnotationsInMetadataFieldSymbolValidator(b.ContainingModule, fieldsBaseline); (bool? constraintIsNullable, string attribute)[] typeParametersBaseline = new[] { ((bool?)null, "System.Runtime.CompilerServices.NullableAttribute(0)"), (false, "System.Runtime.CompilerServices.NullableAttribute(1)"), (true, "System.Runtime.CompilerServices.NullableAttribute(2)"), (null, "System.Runtime.CompilerServices.NullableAttribute(3)"), (null, "System.Runtime.CompilerServices.NullableAttribute(4)"), (null, "System.Runtime.CompilerServices.NullableAttribute(5)"), (null, "System.Runtime.CompilerServices.NullableAttribute({0})"), (null, "System.Runtime.CompilerServices.NullableAttribute({1})"), (null, "System.Runtime.CompilerServices.NullableAttribute({2})"), (null, "System.Runtime.CompilerServices.NullableAttribute({1, 1})"), (null, "System.Runtime.CompilerServices.NullableAttribute({})"), (null, "System.Runtime.CompilerServices.NullableAttribute(null)"), }; Assert.Equal(12, typeParametersBaseline.Length); for (int i = 0; i < typeParametersBaseline.Length; i++) { var t = b.TypeParameters[i]; Assert.Equal(typeParametersBaseline[i].constraintIsNullable, t.ReferenceTypeConstraintIsNullable); Assert.Equal(typeParametersBaseline[i].attribute, t.GetAttributes().Single().ToString()); } } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInFinally_01() { var source = @"public static class Program { public static void Main() { string? s = string.Empty; try { } finally { s = null; } _ = s.Length; // warning } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 13) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_02() { var source = @"public static class Program { public static int Main() { string? s = string.Empty; try { s = null; MayThrow(); s = string.Empty; } catch (System.Exception) { } return s.Length; // warning: possibly null } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,16): warning CS8602: Dereference of a possibly null reference. // return s.Length; // warning: possibly null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(16, 16) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_03() { var source = @"public static class Program { public static int Main() { string? s = string.Empty; try { s = null; MayThrow(); s = string.Empty; } catch (System.Exception) { return s.Length; // warning: possibly null } return s.Length; } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,20): warning CS8602: Dereference of a possibly null reference. // return s.Length; // warning: possibly null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 20) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_04() { var source = @"public static class Program { public static int Main() { string? s = string.Empty; try { s = null; MayThrow(); s = string.Empty; } catch (System.Exception) { _ = s.Length; // warning 1 } finally { _ = s.Length; // warning 2 } return s.Length; // ok (previously dereferenced) } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 17), // (18,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_05() { var source = @"public static class Program { public static int Main() { string? s = null; try { MayThrow(); s = string.Empty; _ = s.Length; // ok } catch (System.Exception) { _ = s.Length; // warning 1 } finally { _ = s.Length; // warning 2 } return s.Length; // ok (previously dereferenced) } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 17), // (18,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_06() { var source = @"public static class Program { public static int Main() { string? s = null; try { MayThrow(); s = string.Empty; _ = s.Length; // ok } catch (System.NullReferenceException) { _ = s.Length; // warning 1 } catch (System.Exception) { _ = s.Length; // warning 2 } finally { _ = s.Length; // warning 3 } return s.Length; // ok (previously dereferenced) } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 17), // (18,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 17), // (22,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(22, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_07() { var source = @"public static class Program { public static int Main() { string? s = null; try { MayThrow(); s = string.Empty; _ = s.Length; // ok } catch (System.NullReferenceException) { _ = s.Length; // warning 1 } catch (System.Exception) { _ = s.Length; // warning 2 } return s.Length; // ok } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 17), // (18,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateBeforeTry_08() { var source = @"public static class Program { public static int Main() { string? s = null; try { MayThrow(); _ = s.Length; // warning 1 } catch (System.NullReferenceException) { _ = s.Length; // warning 2 } catch (System.Exception) { _ = s.Length; // warning 3 } return s.Length; // ok (previously dereferenced) } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 17), // (13,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 17), // (17,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(17, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInTry_09() { var source = @"public static class Program { public static int Main() { string? s = string.Empty; try { s = null; MayThrow(); s = string.Empty; } finally { _ = s.Length; // warning } return s.Length; // ok } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(14, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInCatch_10() { var source = @"public static class Program { public static int Main() { string? s = string.Empty; try { MayThrow(); } catch (System.Exception) { s = null; MayThrow(); s = string.Empty; } finally { _ = s.Length; // warning } return s.Length; // ok } static void MayThrow() { throw null!; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 17) ); } [Fact, WorkItem(30561, "https://github.com/dotnet/roslyn/issues/30561")] public void SetNullableStateInNestedTry_01() { var source = @"public static class Program { public static void Main() { { string? s = string.Empty; try { try { s = null; } catch (System.Exception) { } finally { } } catch (System.Exception) { } finally { } _ = s.Length; // warning 1a } { string? s = string.Empty; try { try { } catch (System.Exception) { s = null; } finally { } } catch (System.Exception) { } finally { } _ = s.Length; // warning 1b } { string? s = string.Empty; try { try { } catch (System.Exception) { } finally { s = null; } } catch (System.Exception) { } finally { } _ = s.Length; // warning 1c } { string? s = string.Empty; try { } catch (System.Exception) { try { s = null; } catch (System.Exception) { } finally { } } finally { _ = s.Length; // warning 2a } } { string? s = string.Empty; try { } catch (System.Exception) { try { } catch (System.Exception) { s = null; } finally { } } finally { _ = s.Length; // warning 2b } } { string? s = string.Empty; try { } catch (System.Exception) { try { } catch (System.Exception) { } finally { s = null; } } finally { _ = s.Length; // warning 2c } } { string? s = string.Empty; try { } catch (System.Exception) { } finally { try { s = null; } catch (System.Exception) { } finally { } } _ = s.Length; // warning 3a } { string? s = string.Empty; try { } catch (System.Exception) { } finally { try { } catch (System.Exception) { s = null; } finally { } } _ = s.Length; // warning 3b } { string? s = string.Empty; try { } catch (System.Exception) { } finally { try { } catch (System.Exception) { } finally { s = null; } } _ = s.Length; // warning 3c } } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (27,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1a Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(27, 17), // (52,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1b Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(52, 17), // (77,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 1c Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(77, 17), // (100,21): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2a Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(100, 21), // (124,21): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2b Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(124, 21), // (148,21): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 2c Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(148, 21), // (174,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 3a Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(174, 17), // (199,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 3b Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(199, 17), // (224,17): warning CS8602: Dereference of a possibly null reference. // _ = s.Length; // warning 3c Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(224, 17) ); } [WorkItem(30938, "https://github.com/dotnet/roslyn/issues/30938")] [Fact] public void ExplicitCastAndInferredTargetType() { var source = @"class Program { static void F(object? x) { if (x == null) return; var y = x; x = null; y = (object)x; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = (object)x; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)x").WithLocation(8, 13)); } [Fact] [WorkItem(31395, "https://github.com/dotnet/roslyn/issues/31395")] public void InheritNullabilityOfNonNullableClassMember() { var source = @"#pragma warning disable 8618 class C { internal T F; } class Program { static void F1(string? s) { var a1 = new C() { F = s }; F(a1.F/*T:string?*/); // 1 var b1 = a1; F(b1.F/*T:string?*/); // 2 } static void F2(T? t) where T : class { var a2 = new C() { F = t }; F(a2.F/*T:T?*/); // 3 var b2 = a2; F(b2.F/*T:T?*/); // 4 } static void F(object o) { } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,40): warning CS8601: Possible null reference assignment. // var a1 = new C() { F = s }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s").WithLocation(10, 40), // (11,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(a1.F/*T:string?*/); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a1.F").WithArguments("o", "void Program.F(object o)").WithLocation(11, 11), // (13,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(b1.F/*T:string?*/); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b1.F").WithArguments("o", "void Program.F(object o)").WithLocation(13, 11), // (17,35): warning CS8601: Possible null reference assignment. // var a2 = new C() { F = t }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t").WithLocation(17, 35), // (18,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(a2.F/*T:T?*/); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a2.F").WithArguments("o", "void Program.F(object o)").WithLocation(18, 11), // (20,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(b2.F/*T:T?*/); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2.F").WithArguments("o", "void Program.F(object o)").WithLocation(20, 11)); comp.VerifyTypes(); } [Fact] public void InheritNullabilityOfNonNullableStructMember() { var source = @"#pragma warning disable 8618 struct S { internal T F; } class Program { static void F1(string? s) { var a1 = new S() { F = s }; F(a1.F/*T:string?*/); // 1 var b1 = a1; F(b1.F/*T:string?*/); // 2 } static void F2(T? t) where T : class { var a2 = new S() { F = t }; F(a2.F/*T:T?*/); // 3 var b2 = a2; F(b2.F/*T:T?*/); // 4 } static void F(object o) { } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,40): warning CS8601: Possible null reference assignment. // var a1 = new S() { F = s }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "s").WithLocation(10, 40), // (11,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(a1.F/*T:string?*/); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a1.F").WithArguments("o", "void Program.F(object o)").WithLocation(11, 11), // (13,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(b1.F/*T:string?*/); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b1.F").WithArguments("o", "void Program.F(object o)").WithLocation(13, 11), // (17,35): warning CS8601: Possible null reference assignment. // var a2 = new S() { F = t }; Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "t").WithLocation(17, 35), // (18,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(a2.F/*T:T?*/); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "a2.F").WithArguments("o", "void Program.F(object o)").WithLocation(18, 11), // (20,11): warning CS8604: Possible null reference argument for parameter 'o' in 'void Program.F(object o)'. // F(b2.F/*T:T?*/); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2.F").WithArguments("o", "void Program.F(object o)").WithLocation(20, 11)); comp.VerifyTypes(); } /// /// Nullability of variable members is tracked up to a fixed depth. /// [Fact] [WorkItem(31395, "https://github.com/dotnet/roslyn/issues/31395")] public void InheritNullabilityMaxDepth_01() { var source = @"#pragma warning disable 8618 class A { internal B? B; } class B { internal A? A; } class Program { static void F() { var a1 = new A() { B = new B() }; var a2 = new A() { B = new B() { A = a1 } }; var a3 = new A() { B = new B() { A = a2 } }; a1.B.ToString(); a2.B.A.B.ToString(); a3.B.A.B.A.B.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // a3.B.A.B.A.B.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a3.B.A.B.A.B").WithLocation(19, 9)); } /// /// Nullability of variable members is tracked up to a fixed depth. /// [Fact] [WorkItem(31395, "https://github.com/dotnet/roslyn/issues/31395")] public void InheritNullabilityMaxDepth_02() { var source = @"class Program { static void F(string x, object y) { (((((string? x5, object? y5) x4, string? y4) x3, object? y3) x2, string? y2) x1, object? y1) t = (((((x, y), x), y), x), y); t.y1.ToString(); t.x1.y2.ToString(); t.x1.x2.y3.ToString(); t.x1.x2.x3.y4.ToString(); t.x1.x2.x3.x4.y5.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // t.x1.x2.x3.x4.y5.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.x1.x2.x3.x4.y5").WithLocation(10, 9)); } /// /// Nullability of variable members is tracked up to a fixed depth. /// [Fact] [WorkItem(31395, "https://github.com/dotnet/roslyn/issues/31395")] [WorkItem(35773, "https://github.com/dotnet/roslyn/issues/35773")] public void InheritNullabilityMaxDepth_03() { var source = @"class Program { static void Main() { (((((string x5, string y5) x4, string y4) x3, string y3) x2, string y2) x1, string y1) t = default; t.x1.x2.x3.x4.x5.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void DiagnosticOptions_01() { var source = @" partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } private static void AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(string source) { string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable); var source2 = @" partial class Program { #nullable enable static void F(object o) { } }"; var comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics(); foreach (ReportDiagnostic option in Enum.GetValues(typeof(ReportDiagnostic))) { comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithSpecificDiagnosticOptions(id, option)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithGeneralDiagnosticOption(option)); comp.VerifyDiagnostics(); } assertDiagnosticOptions(NullableContextOptions.Enable); assertDiagnosticOptions(NullableContextOptions.Warnings); void assertDiagnosticOptions(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions); var diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): error CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error). WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): error CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): error CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); } } [Fact] public void DiagnosticOptions_02() { var source = @" #pragma warning disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } private static void AssertDiagnosticOptions_NullableWarningsNeverGiven(string source) { string id1 = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable); string id2 = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable); var source2 = @" partial class Program { #nullable enable static void F(object o) { } static object M() { return new object(); } }"; var comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics(); foreach (ReportDiagnostic option in Enum.GetValues(typeof(ReportDiagnostic))) { comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithSpecificDiagnosticOptions(id1, id2, option)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithGeneralDiagnosticOption(option)); comp.VerifyDiagnostics(); } assertDiagnosticOptions(NullableContextOptions.Disable); assertDiagnosticOptions(NullableContextOptions.Enable); assertDiagnosticOptions(NullableContextOptions.Warnings); assertDiagnosticOptions(NullableContextOptions.Annotations); void assertDiagnosticOptions(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Default)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithGeneralDiagnosticOption(ReportDiagnostic.Default)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Error)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Error). WithGeneralDiagnosticOption(ReportDiagnostic.Default)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Error)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Suppress)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Suppress). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Suppress)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Hidden)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Hidden). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id1, id2, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); comp.VerifyDiagnostics(); } } [Fact] public void DiagnosticOptions_03() { var source = @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_04() { var source = @" #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_05() { var source = @" #nullable disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_06() { var source = @" #nullable enable partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(source); } private static void AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(string source) { var source2 = @" partial class Program { #nullable enable static void F(object o) { } }"; assertDiagnosticOptions(NullableContextOptions.Disable); assertDiagnosticOptions(NullableContextOptions.Enable); assertDiagnosticOptions(NullableContextOptions.Warnings); assertDiagnosticOptions(NullableContextOptions.Annotations); void assertDiagnosticOptions(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions options = WithNonNullTypes(nullableContextOptions); string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable); var comp = CreateCompilation(new[] { source, source2 }, options: options); var diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 11) ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options.WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): error CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error). WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): error CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): error CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: options. WithGeneralDiagnosticOption(ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (6,11): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); } } [Fact] public void DiagnosticOptions_07() { var source = @" #pragma warning disable #nullable disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_08() { var source = @" #pragma warning disable #nullable enable partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_09() { var source = @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" #nullable disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_10() { var source = @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" #nullable enable partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_11() { var source = @" #nullable disable #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_12() { var source = @" #nullable disable #pragma warning disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_13() { var source = @" #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" #nullable disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_14() { var source = @" #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" #nullable enable partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_15() { var source = @" #nullable disable #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_16() { var source = @" #pragma warning restore partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_17() { var source = @" #nullable disable #pragma warning restore partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_18() { var source = @" #pragma warning restore #nullable disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_19() { var source = @" #nullable enable #pragma warning restore partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_20() { var source = @" #pragma warning restore #nullable enable partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_21() { var source = @" #nullable enable #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @" partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_22() { var source = @" #nullable restore partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_23() { var source = @" #nullable safeonly "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (2,11): error CS8637: Expected 'enable', 'disable', or 'restore' // #nullable safeonly Diagnostic(ErrorCode.ERR_NullableDirectiveQualifierExpected, "safeonly").WithLocation(2, 11) ); } [Fact] public void DiagnosticOptions_26() { var source = @" #nullable restore #nullable disable partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_27() { var source = @" #nullable restore #nullable enable partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_30() { var source = @" #nullable disable #nullable restore partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_32() { var source = @" #nullable enable #nullable restore partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_36() { var source = @" partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } private static void AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(string source) { var source2 = @" partial class Program { #nullable enable static object M() { return new object(); } }"; string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable); assertDiagnosticOptions1(NullableContextOptions.Enable); assertDiagnosticOptions1(NullableContextOptions.Warnings); assertDiagnosticOptions2(NullableContextOptions.Disable); assertDiagnosticOptions2(NullableContextOptions.Annotations); void assertDiagnosticOptions1(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions); var diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): error CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error). WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): error CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): error CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): hidden CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): hidden CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); } void assertDiagnosticOptions2(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions compilationOptions = WithNonNullTypes(nullableContextOptions); var comp = CreateCompilation(new[] { source, source2 }, options: compilationOptions); comp.VerifyDiagnostics(); foreach (ReportDiagnostic option in Enum.GetValues(typeof(ReportDiagnostic))) { comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithSpecificDiagnosticOptions(id, option)); comp.VerifyDiagnostics(); comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithGeneralDiagnosticOption(option)); comp.VerifyDiagnostics(); } } } [Fact] public void DiagnosticOptions_37() { var source = @" #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_38() { var source = @" #nullable enable partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } private static void AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(string source) { var source2 = @" partial class Program { #nullable enable static object M() { return new object(); } }"; assertDiagnosticOptions(NullableContextOptions.Disable); assertDiagnosticOptions(NullableContextOptions.Enable); assertDiagnosticOptions(NullableContextOptions.Warnings); assertDiagnosticOptions(NullableContextOptions.Annotations); void assertDiagnosticOptions(NullableContextOptions nullableContextOptions) { CSharpCompilationOptions options = WithNonNullTypes(nullableContextOptions); string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable); var comp = CreateCompilation(new[] { source, source2 }, options: options); var diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options.WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): error CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error). WithGeneralDiagnosticOption(ReportDiagnostic.Default)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): error CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): error CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithWarningAsError(true) ); Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: options. WithGeneralDiagnosticOption(ReportDiagnostic.Suppress)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify(); comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): hidden CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden). WithGeneralDiagnosticOption(ReportDiagnostic.Error)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): hidden CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); comp = CreateCompilation(new[] { source, source2 }, options: options. WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default). WithGeneralDiagnosticOption(ReportDiagnostic.Hidden)); diagnostics = comp.GetDiagnostics(); diagnostics.Verify( // (8,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null") ); Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity); } } [Fact] public void DiagnosticOptions_39() { var source = @" #pragma warning disable #nullable enable partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_40() { var source = @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" #nullable enable partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_41() { var source = @" #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" #nullable enable partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_42() { var source = @" #nullable disable #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_43() { var source = @" #pragma warning restore partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_44() { var source = @" #nullable disable #pragma warning restore partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_45() { var source = @" #nullable enable #pragma warning restore partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_46() { var source = @" #pragma warning restore #nullable enable partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_48() { var source = @" #nullable enable #pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_49() { var source = @" #nullable restore partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_53() { var source = @" #nullable restore #nullable enable partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_56() { var source = @" #nullable disable #nullable restore partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_58() { var source = @" #nullable enable #nullable restore partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_62() { var source = @" #nullable disable warnings partial class Program { static void Test() { F(null); var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_63() { var source = @" #nullable enable warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_64() { var source = @" #pragma warning disable #nullable enable warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_65() { var source = @" #pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ConvertingNullableToNonNullable) + @" #nullable enable warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableWarningsNeverGiven(source); } [Fact] public void DiagnosticOptions_66() { var source = @" #pragma warning restore #nullable enable warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_67() { var source = @" #nullable restore #nullable enable warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_UnlessDisabledByDiagnosticOptions(source); } [Fact] public void DiagnosticOptions_68() { var source = @" #nullable restore warnings partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_69() { var source = @" #nullable disable #nullable restore warnings partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_70() { var source = @" #nullable enable #nullable restore warnings partial class Program { static void Test() { F(null); } }"; AssertDiagnosticOptions_NullableWarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_72() { var source = @" #nullable restore warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_73() { var source = @" #nullable disable #nullable restore warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] public void DiagnosticOptions_74() { var source = @" #nullable enable #nullable restore warnings partial class Program { static void Test() { var x = M(); x = null; } }"; AssertDiagnosticOptions_NullableW_WarningsGiven_OnlyWhenEnabledInProject(source); } [Fact] [WorkItem(31394, "https://github.com/dotnet/roslyn/issues/31394")] public void InheritMemberNullability_Class() { var source = @"#pragma warning disable 8618 class C { internal T F; } class Program { static void F() { C x = new C() { F = null }; x.F/*T:object?*/.ToString(); // 1 C y = new C() { F = new object() }; y.F/*T:object!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,23): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // C x = new C() { F = null }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new C() { F = null }").WithArguments("C", "C").WithLocation(10, 23), // (11,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(11, 9), // (12,24): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // C y = new C() { F = new object() }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new C() { F = new object() }").WithArguments("C", "C").WithLocation(12, 24)); comp.VerifyTypes(); } [Fact] [WorkItem(31394, "https://github.com/dotnet/roslyn/issues/31394")] public void InheritMemberNullability_Struct() { var source = @"#pragma warning disable 8618 struct S { internal T F; } class Program { static void F() { S x = new S(); x.F/*T:object?*/.ToString(); // 1 S y = new S() { F = new object() }; y.F/*T:object!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,23): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S'. // S x = new S(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new S()").WithArguments("S", "S").WithLocation(10, 23), // (11,9): warning CS8602: Dereference of a possibly null reference. // x.F/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.F").WithLocation(11, 9), // (12,24): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S'. // S y = new S() { F = new object() }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new S() { F = new object() }").WithArguments("S", "S").WithLocation(12, 24)); comp.VerifyTypes(); } [Fact] [WorkItem(31394, "https://github.com/dotnet/roslyn/issues/31394")] public void InheritMemberNullability_AnonymousTypeField() { var source = @"class C { } class Program { static void F1(C x1, C? y1) { var a1 = new { F = x1 }; a1.F/*T:C!*/.ToString(); a1 = new { F = y1 }; a1.F/*T:C?*/.ToString(); // 1 } static void F2(C? x2, C y2) { var a2 = new { F = x2 }; a2.F/*T:C?*/.ToString(); // 2 a2 = new { F = y2 }; a2.F/*T:C!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // a1 = new { F = y1 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new { F = y1 }").WithArguments(" F>", " F>").WithLocation(8, 14), // (9,9): warning CS8602: Dereference of a possibly null reference. // a1.F/*T:C?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a1.F").WithLocation(9, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // a2.F/*T:C?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2.F").WithLocation(14, 9), // (15,14): warning CS8619: Nullability of reference types in value of type ' F>' doesn't match target type ' F>'. // a2 = new { F = y2 }; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "new { F = y2 }").WithArguments(" F>", " F>").WithLocation(15, 14)); comp.VerifyTypes(); } [Fact] [WorkItem(31394, "https://github.com/dotnet/roslyn/issues/31394")] public void InheritMemberNullability_TupleElement_01() { var source = @"class C { } class Program { static void F1(C x1, C? y1) { var t1 = (x1, y1); t1.Item1/*T:C!*/.ToString(); t1 = (y1, y1); t1.Item1/*T:C?*/.ToString(); // 1 } static void F2(C? x2, C y2) { var t2 = (x2, y2); t2.Item1/*T:C?*/.ToString(); // 2 t2 = (y2, y2); t2.Item1/*T:C!*/.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,14): warning CS8619: Nullability of reference types in value of type '(C?, C?)' doesn't match target type '(C x1, C? y1)'. // t1 = (y1, y1); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y1, y1)").WithArguments("(C?, C?)", "(C x1, C? y1)").WithLocation(8, 14), // (9,9): warning CS8602: Dereference of a possibly null reference. // t1.Item1/*T:C?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1.Item1").WithLocation(9, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // t2.Item1/*T:C?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2.Item1").WithLocation(14, 9), // (15,14): warning CS8619: Nullability of reference types in value of type '(C, C)' doesn't match target type '(C? x2, C y2)'. // t2 = (y2, y2); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y2, y2)").WithArguments("(C, C)", "(C? x2, C y2)").WithLocation(15, 14)); comp.VerifyTypes(); } [Fact] [WorkItem(31394, "https://github.com/dotnet/roslyn/issues/31394")] public void InheritMemberNullability_TupleElement_02() { var source = @"class C { } class Program { static void F(C x, C? y) { (C? a, C b) t = (x, y); t.a/*T:C!*/.ToString(); t.b/*T:C?*/.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,42): warning CS8619: Nullability of reference types in value of type '(C x, C? y)' doesn't match target type '(C? a, C b)'. // (C? a, C b) t = (x, y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, y)").WithArguments("(C x, C? y)", "(C? a, C b)").WithLocation(6, 42), // (8,9): warning CS8602: Dereference of a possibly null reference. // t.b/*T:C?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.b").WithLocation(8, 9)); comp.VerifyTypes(); } private readonly static NullableAnnotation[] s_AllNullableAnnotations = (NullableAnnotation[])Enum.GetValues(typeof(NullableAnnotation)); private readonly static NullableFlowState[] s_AllNullableFlowStates = (NullableFlowState[])Enum.GetValues(typeof(NullableFlowState)); [Fact] public void TestJoinForNullableAnnotations() { var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }; Func getResult = (i, j) => NullableAnnotationExtensions.Join(inputs[i], inputs[j]); var expected = new NullableAnnotation[3, 3] { { NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.Annotated }, { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.Oblivious }, { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }, }; AssertEqual(expected, getResult, inputs.Length); } [Fact] public void TestJoinForNullableFlowStates() { var inputs = new[] { NullableFlowState.NotNull, NullableFlowState.MaybeNull }; Func getResult = (i, j) => inputs[i].Join(inputs[j]); var expected = new NullableFlowState[2, 2] { { NullableFlowState.NotNull, NullableFlowState.MaybeNull }, { NullableFlowState.MaybeNull, NullableFlowState.MaybeNull }, }; AssertEqual(expected, getResult, inputs.Length); } [Fact] public void TestMeetForNullableAnnotations() { var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }; Func getResult = (i, j) => NullableAnnotationExtensions.Meet(inputs[i], inputs[j]); var expected = new NullableAnnotation[3, 3] { { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }, { NullableAnnotation.Oblivious, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }, { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, }; AssertEqual(expected, getResult, inputs.Length); } [Fact] public void TestMeetForNullableFlowStates() { var inputs = new[] { NullableFlowState.NotNull, NullableFlowState.MaybeNull }; Func getResult = (i, j) => inputs[i].Meet(inputs[j]); var expected = new NullableFlowState[2, 2] { { NullableFlowState.NotNull, NullableFlowState.NotNull }, { NullableFlowState.NotNull, NullableFlowState.MaybeNull }, }; AssertEqual(expected, getResult, inputs.Length); } [Fact] public void TestEnsureCompatible() { var inputs = new[] { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }; Func getResult = (i, j) => NullableAnnotationExtensions.EnsureCompatible(inputs[i], inputs[j]); var expected = new NullableAnnotation[3, 3] { { NullableAnnotation.Annotated, NullableAnnotation.Annotated, NullableAnnotation.NotAnnotated }, { NullableAnnotation.Annotated, NullableAnnotation.Oblivious, NullableAnnotation.NotAnnotated }, { NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated, NullableAnnotation.NotAnnotated }, }; AssertEqual(expected, getResult, inputs.Length); } private static void AssertEqual(NullableAnnotation[,] expected, Func getResult, int size) { AssertEx.Equal(expected, getResult, (na1, na2) => na1 == na2, na => $"NullableAnnotation.{na}", "{0,-32:G}", size); } private static void AssertEqual(NullableFlowState[,] expected, Func getResult, int size) { AssertEx.Equal(expected, getResult, (na1, na2) => na1 == na2, na => $"NullableFlowState.{na}", "{0,-32:G}", size); } [Fact] public void TestAbsorptionForNullableAnnotations() { foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { Assert.Equal(a, a.Meet(a.Join(b))); Assert.Equal(a, a.Join(a.Meet(b))); } } } [Fact] public void TestAbsorptionForNullableFlowStates() { foreach (var a in s_AllNullableFlowStates) { foreach (var b in s_AllNullableFlowStates) { Assert.Equal(a, a.Meet(a.Join(b))); Assert.Equal(a, a.Join(a.Meet(b))); } } } [Fact] public void TestJoinForNullableAnnotationsIsAssociative() { foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { foreach (var c in s_AllNullableAnnotations) { var leftFirst = a.Join(b).Join(c); var rightFirst = a.Join(b.Join(c)); Assert.Equal(leftFirst, rightFirst); } } } } [Fact] public void TestJoinForNullableFlowStatesIsAssociative() { foreach (var a in s_AllNullableFlowStates) { foreach (var b in s_AllNullableFlowStates) { foreach (var c in s_AllNullableFlowStates) { var leftFirst = a.Join(b).Join(c); var rightFirst = a.Join(b.Join(c)); Assert.Equal(leftFirst, rightFirst); } } } } [Fact] public void TestMeetForNullableAnnotationsIsAssociative() { foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { foreach (var c in s_AllNullableAnnotations) { var leftFirst = a.Meet(b).Meet(c); var rightFirst = a.Meet(b.Meet(c)); Assert.Equal(leftFirst, rightFirst); } } } } [Fact] public void TestMeetForNullableFlowStatesIsAssociative() { foreach (var a in s_AllNullableFlowStates) { foreach (var b in s_AllNullableFlowStates) { foreach (var c in s_AllNullableFlowStates) { var leftFirst = a.Meet(b).Meet(c); var rightFirst = a.Meet(b.Meet(c)); Assert.Equal(leftFirst, rightFirst); } } } } [Fact] public void TestEnsureCompatibleIsAssociative() { Func identity = x => x; foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { foreach (var c in s_AllNullableAnnotations) { foreach (bool isPossiblyNullableReferenceTypeTypeParameter in new[] { true, false }) { var leftFirst = a.EnsureCompatible(b).EnsureCompatible(c); var rightFirst = a.EnsureCompatible(b.EnsureCompatible(c)); Assert.Equal(leftFirst, rightFirst); } } } } } [Fact] public void TestJoinForNullableAnnotationsIsCommutative() { foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { var leftFirst = a.Join(b); var rightFirst = b.Join(a); Assert.Equal(leftFirst, rightFirst); } } } [Fact] public void TestJoinForNullableFlowStatesIsCommutative() { Func identity = x => x; foreach (var a in s_AllNullableFlowStates) { foreach (var b in s_AllNullableFlowStates) { var leftFirst = a.Join(b); var rightFirst = b.Join(a); Assert.Equal(leftFirst, rightFirst); } } } [Fact] public void TestMeetForNullableAnnotationsIsCommutative() { foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { var leftFirst = a.Meet(b); var rightFirst = b.Meet(a); Assert.Equal(leftFirst, rightFirst); } } } [Fact] public void TestMeetForNullableFlowStatesIsCommutative() { foreach (var a in s_AllNullableFlowStates) { foreach (var b in s_AllNullableFlowStates) { var leftFirst = a.Meet(b); var rightFirst = b.Meet(a); Assert.Equal(leftFirst, rightFirst); } } } [Fact] public void TestEnsureCompatibleIsCommutative() { foreach (var a in s_AllNullableAnnotations) { foreach (var b in s_AllNullableAnnotations) { var leftFirst = a.EnsureCompatible(b); var rightFirst = b.EnsureCompatible(a); Assert.Equal(leftFirst, rightFirst); } } } [Fact] public void NullableT_CSharp7() { var source = @"class Program { static void F(T? x) where T : struct { _ = x.Value; } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // error CS8630: Invalid 'NullableContextOptions' value: 'Enable' for C# 7.0. Please use language version 'preview' or greater. Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("NullableContextOptions", "Enable", "7.0", "preview").WithLocation(1, 1) ); } [Fact] public void NullableT_WarningDisabled() { var source = @"#nullable disable //#nullable disable warnings class Program { static void F(T? x) where T : struct { _ = x.Value; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact] public void NullableT_01() { var source = @"class Program { static void F(T? x) where T : struct { _ = x.Value; // 1 _ = x.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,13): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(5, 13) ); } [Fact] public void NullableT_02() { var source = @"class Program { static void F(T x) where T : struct { T? y = x; _ = y.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_03() { var source = @"class Program { static void F(T? x) where T : struct { T y = x; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,15): error CS0266: Cannot implicitly convert type 'T?' to 'T'. An explicit conversion exists (are you missing a cast?) // T y = x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("T?", "T").WithLocation(5, 15), // (5,15): warning CS8629: Nullable value type may be null. // T y = x; Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(5, 15)); } [Fact] public void NullableT_04() { var source = @"class Program { static T F1(T? x) where T : struct { return (T)x; // 1 } static T F2() where T : struct { return (T)default(T?); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,16): warning CS8629: Nullable value type may be null. // return (T)x; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)x").WithLocation(5, 16), // (9,16): warning CS8629: Nullable value type may be null. // return (T)default(T?); // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)default(T?)").WithLocation(9, 16)); } [Fact] public void NullableT_05() { var source = @"using System; class Program { static void F() where T : struct { _ = nameof(Nullable.HasValue); _ = nameof(Nullable.Value); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_06() { var source = @"class Program { static void F(T? x, T? y) where T : struct { _ = (T)x; // 1 _ = (T)x; x = y; _ = (T)x; // 2 _ = (T)x; _ = (T)y; // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,13): warning CS8629: Nullable value type may be null. // _ = (T)x; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)x").WithLocation(5, 13), // (8,13): warning CS8629: Nullable value type may be null. // _ = (T)x; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)x").WithLocation(8, 13), // (10,13): warning CS8629: Nullable value type may be null. // _ = (T)y; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y").WithLocation(10, 13)); } [Fact] public void NullableT_07() { var source = @"class Program { static void F1((int, int) x) { (int, int)? y = x; _ = y.Value; var z = ((int, int))y; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_08() { var source = @"class Program { static void F1((int, int)? x) { var y = ((int, int))x; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,17): warning CS8629: Nullable value type may be null. // var y = ((int, int))x; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "((int, int))x").WithLocation(5, 17)); } [Fact] public void NullableT_09() { var source = @"class Program { static void F(T t) where T : struct { T? x = null; _ = x.Value; // 1 T? y = default; _ = y.Value; // 2 T? z = default(T); _ = z.Value; T? w = t; _ = w.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(6, 13), // (8,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(8, 13) ); } [WorkItem(31502, "https://github.com/dotnet/roslyn/issues/31502")] [Fact] public void NullableT_10() { var source = @"class Program { static void F(T t) where T : struct { T? x = new System.Nullable(); _ = x.Value; // 1 T? y = new System.Nullable(t); _ = y.Value; T? z = new T?(); _ = z.Value; // 2 T? w = new T?(t); _ = w.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(6, 13), // (10,13): warning CS8629: Nullable value type may be null. // _ = z.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(10, 13) ); } [Fact] public void NullableT_11() { var source = @"class C where T : struct { static void F1(T? t1) { if (t1.HasValue) _ = t1.Value; else _ = t1.Value; // 1 } static void F2(T? t2) { if (!t2.HasValue) _ = t2.Value; // 2 else _ = t2.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(8, 17), // (13,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 17) ); } [Fact] public void NullableT_12() { var source = @"class C where T : struct { static void F1(T? t1) { if (t1 != null) _ = t1.Value; else _ = t1.Value; // 1 } static void F2(T? t2) { if (t2 == null) _ = t2.Value; // 2 else _ = t2.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(8, 17), // (13,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 17) ); } [Fact] public void NullableT_13() { var source = @"class C where T : struct { static void F1(T? t1) { if (null != t1) _ = (T)t1; else _ = (T)t1; // 1 } static void F2(T? t2) { if (null == t2) { var o2 = (object)t2; // 2 o2.ToString(); // 3 } else { var o2 = (object)t2; o2.ToString(); } } static void F3(T? t3) { if (null == t3) { var d3 = (dynamic)t3; // 4 d3.ToString(); // 5 } else { var d3 = (dynamic)t3; d3.ToString(); } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,17): warning CS8629: Nullable value type may be null. // _ = (T)t1; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)t1").WithLocation(8, 17), // (14,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var o2 = (object)t2; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)t2").WithLocation(14, 22), // (15,13): warning CS8602: Dereference of a possibly null reference. // o2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o2").WithLocation(15, 13), // (27,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var d3 = (dynamic)t3; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(dynamic)t3").WithLocation(27, 22), // (28,13): warning CS8602: Dereference of a possibly null reference. // d3.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d3").WithLocation(28, 13)); } [Fact] public void NullableT_14() { var source = @"class C where T : struct { static void F1(T? t1) { if (t1.HasValue) { if (t1.HasValue) _ = t1.Value; else _ = t1.Value; } } static void F2(T? t2) { if (t2 != null) { if (!t2.HasValue) _ = t2.Value; else _ = t2.Value; } } static void F3(T? t3) { if (!t3.HasValue) { if (t3 != null) _ = t3.Value; else _ = t3.Value; // 1 } } static void F4(T? t4) { if (t4 == null) { if (t4 == null) _ = t4.Value; // 2 else _ = t4.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (24,22): warning CS8629: Nullable value type may be null. // else _ = t3.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(24, 22), // (31,33): warning CS8629: Nullable value type may be null. // if (t4 == null) _ = t4.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(31, 33) ); } [Fact] public void NullableT_15() { var source = @"class C where T : struct { static void F1(T? x1, T? y1) { _ = x1.HasValue ? x1.Value : y1.Value; // 1 } static void F2(T? x2, T? y2) { _ = !x2.HasValue ? y2.Value : // 2 x2.Value; } static void F3(T? x3, T? y3) { _ = x3.HasValue || y3.HasValue ? x3.Value : // 3 y3.Value; // 4 } static void F4(T? x4, T? y4) { _ = x4.HasValue && y4.HasValue ? (T)x4 : (T)y4; // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8629: Nullable value type may be null. // y1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(7, 13), // (12,13): warning CS8629: Nullable value type may be null. // y2.Value : // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2").WithLocation(12, 13), // (18,13): warning CS8629: Nullable value type may be null. // x3.Value : // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3").WithLocation(18, 13), // (19,13): warning CS8629: Nullable value type may be null. // y3.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3").WithLocation(19, 13), // (25,13): warning CS8629: Nullable value type may be null. // (T)y4; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y4").WithLocation(25, 13) ); } [Fact] public void NullableT_16() { var source = @"class C where T : struct { static void F1(T? x1, T? y1) { _ = x1 != null ? x1.Value : y1.Value; // 1 } static void F2(T? x2, T? y2) { _ = x2 == null ? y2.Value : // 2 x2.Value; } static void F3(T? x3, T? y3) { _ = x3 != null || y3 != null ? x3.Value : // 3 y3.Value; // 4 } static void F4(T? x4, T? y4) { _ = x4 != null && y4 != null ? (T)x4 : (T)y4; // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8629: Nullable value type may be null. // y1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1").WithLocation(7, 13), // (12,13): warning CS8629: Nullable value type may be null. // y2.Value : // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2").WithLocation(12, 13), // (18,13): warning CS8629: Nullable value type may be null. // x3.Value : // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3").WithLocation(18, 13), // (19,13): warning CS8629: Nullable value type may be null. // y3.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3").WithLocation(19, 13), // (25,13): warning CS8629: Nullable value type may be null. // (T)y4; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)y4").WithLocation(25, 13) ); } [Fact, WorkItem(33924, "https://github.com/dotnet/roslyn/issues/33924")] public void NullableT_17() { var source = @"class C where T : struct { static void F1(T? x1, T? y1) { _ = (T)(x1 != null ? x1 : y1); // 1 } static void F2(T? x2, T? y2) { if (y2 == null) return; _ = (T)(x2 != null ? x2 : y2); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,13): warning CS8629: Nullable value type may be null. // _ = (T)(x1 != null ? x1 : y1); // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)(x1 != null ? x1 : y1)").WithLocation(5, 13)); } [Fact] public void NullableT_18() { var source = @"class C where T : struct { static void F1(T? x1, T? y1) { object? z1 = x1 != null ? (object?)x1 : y1; _ = z1/*T:object?*/.ToString(); // 1 dynamic? w1 = x1 != null ? (dynamic?)x1 : y1; _ = w1/*T:dynamic?*/.ToString(); // 2 } static void F2(T? x2, T? y2) { if (y2 == null) return; object? z2 = x2 != null ? (object?)x2 : y2; _ = z2/*T:object?*/.ToString(); // 3 dynamic? w2 = x2 != null ? (dynamic?)x2 : y2; _ = w2/*T:dynamic?*/.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8602: Dereference of a possibly null reference. // _ = z1/*T:object?*/.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(6, 13), // (8,13): warning CS8602: Dereference of a possibly null reference. // _ = w1/*T:dynamic?*/.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w1").WithLocation(8, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // _ = z2/*T:object!*/.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(14, 13), // (16,13): warning CS8602: Dereference of a possibly null reference. // _ = w2/*T:dynamic!*/.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(16, 13) ); comp.VerifyTypes(); } [Fact] public void NullableT_19() { var source = @"#pragma warning disable 0649 struct A { internal B? B; } struct B { internal C? C; } struct C { } class Program { static void F1(A? na1) { if (na1?.B?.C != null) { _ = na1.Value.B.Value.C.Value; } else { A a1 = na1.Value; // 1 B b1 = a1.B.Value; // 2 C c1 = b1.C.Value; // 3 } } static void F2(A? na2) { if (na2?.B?.C != null) { _ = (C)((B)((A)na2).B).C; } else { A a2 = (A)na2; // 4 B b2 = (B)a2.B; // 5 C c2 = (C)b2.C; // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,20): warning CS8629: Nullable value type may be null. // A a1 = na1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "na1").WithLocation(23, 20), // (24,20): warning CS8629: Nullable value type may be null. // B b1 = a1.B.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "a1.B").WithLocation(24, 20), // (25,20): warning CS8629: Nullable value type may be null. // C c1 = b1.C.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b1.C").WithLocation(25, 20), // (36,20): warning CS8629: Nullable value type may be null. // A a2 = (A)na2; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(A)na2").WithLocation(36, 20), // (37,20): warning CS8629: Nullable value type may be null. // B b2 = (B)a2.B; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(B)a2.B").WithLocation(37, 20), // (38,20): warning CS8629: Nullable value type may be null. // C c2 = (C)b2.C; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(C)b2.C").WithLocation(38, 20) ); } [Fact] public void NullableT_20() { var source = @"#pragma warning disable 0649 struct A { internal B? B; } struct B { } class Program { static void F1(A? na1) { if (na1?.B != null) { var a1 = (object)na1; a1.ToString(); } else { var a1 = (object)na1; // 1 a1.ToString(); // 2 } } static void F2(A? na2) { if (na2?.B != null) { var a2 = (System.ValueType)na2; a2.ToString(); } else { var a2 = (System.ValueType)na2; // 3 a2.ToString(); // 4 } } static void F3(A? na3) { if (na3?.B != null) { var a3 = (A)na3; var b3 = (object)a3.B; b3.ToString(); } else { var a3 = (A)na3; // 5 var b3 = (object)a3.B; // 6 b3.ToString(); // 7 } } static void F4(A? na4) { if (na4?.B != null) { var a4 = (A)na4; var b4 = (System.ValueType)a4.B; b4.ToString(); } else { var a4 = (A)na4; // 8 var b4 = (System.ValueType)a4.B; // 9 b4.ToString(); // 10 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var a1 = (object)na1; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)na1").WithLocation(20, 22), // (21,13): warning CS8602: Dereference of a possibly null reference. // a1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a1").WithLocation(21, 13), // (33,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var a2 = (System.ValueType)na2; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(System.ValueType)na2").WithLocation(33, 22), // (34,13): warning CS8602: Dereference of a possibly null reference. // a2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a2").WithLocation(34, 13), // (47,22): warning CS8629: Nullable value type may be null. // var a3 = (A)na3; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(A)na3").WithLocation(47, 22), // (48,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var b3 = (object)a3.B; // 6 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)a3.B").WithLocation(48, 22), // (49,13): warning CS8602: Dereference of a possibly null reference. // b3.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b3").WithLocation(49, 13), // (62,22): warning CS8629: Nullable value type may be null. // var a4 = (A)na4; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(A)na4").WithLocation(62, 22), // (63,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var b4 = (System.ValueType)a4.B; // 9 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(System.ValueType)a4.B").WithLocation(63, 22), // (64,13): warning CS8602: Dereference of a possibly null reference. // b4.ToString(); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b4").WithLocation(64, 13)); } [Fact] public void NullableT_21() { var source = @"#pragma warning disable 0649 struct A { internal B? B; public static implicit operator C(A a) => new C(); } struct B { public static implicit operator C(B b) => new C(); } class C { } class Program { static void F1(A? na1) { if (na1?.B != null) { var c1 = (C)na1; c1.ToString(); } else { var c1 = (C)na1; // 1 c1.ToString(); // 2 } } static void F2(A? na2) { if (na2?.B != null) { var a2 = (A)na2; var c2 = (C)a2.B; c2.ToString(); } else { var a2 = (A)na2; // 3 var c2 = (C)a2.B; // 4 c2.ToString(); // 5 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (25,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var c1 = (C)na1; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)na1").WithLocation(25, 22), // (26,13): warning CS8602: Dereference of a possibly null reference. // c1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(26, 13), // (39,22): warning CS8629: Nullable value type may be null. // var a2 = (A)na2; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(A)na2").WithLocation(39, 22), // (40,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // var c2 = (C)a2.B; // 4 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(C)a2.B").WithLocation(40, 22), // (41,13): warning CS8602: Dereference of a possibly null reference. // c2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(41, 13)); } [Fact] public void NullableT_22() { var source = @"#pragma warning disable 0649 struct S { internal C? C; } class C { internal S? S; } class Program { static void F1(S? ns) { if (ns?.C != null) { _ = ns.Value.C.ToString(); } else { var s = ns.Value; // 1 var c = s.C; c.ToString(); // 2 } } static void F2(C? nc) { if (nc?.S != null) { _ = nc.S.Value; } else { var ns = nc.S; // 3 _ = ns.Value; // 4 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (20,21): warning CS8629: Nullable value type may be null. // var s = ns.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns").WithLocation(20, 21), // (22,13): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(22, 13), // (34,22): warning CS8602: Dereference of a possibly null reference. // var ns = nc.S; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "nc").WithLocation(34, 22), // (35,17): warning CS8629: Nullable value type may be null. // _ = ns.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns").WithLocation(35, 17) ); } [Fact] public void NullableT_IntToLong() { var source = @"class Program { // int -> long? static void F1(int i) { var nl1 = (long?)i; _ = nl1.Value; long? nl2 = i; _ = nl2.Value; int? ni = i; long? nl3 = ni; _ = nl3.Value; } // int? -> long? static void F2(int? ni) { if (ni.HasValue) { long? nl1 = ni; _ = nl1.Value; var nl2 = (long?)ni; _ = nl2.Value; } else { long? nl3 = ni; _ = nl3.Value; // 1 var nl4 = (long?)ni; _ = nl4.Value; // 2 } } // int? -> long static void F3(int? ni) { if (ni.HasValue) { _ = (long)ni; } else { _ = (long)ni; // 3 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (27,17): warning CS8629: Nullable value type may be null. // _ = nl3.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl3").WithLocation(27, 17), // (29,17): warning CS8629: Nullable value type may be null. // _ = nl4.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl4").WithLocation(29, 17), // (41,17): warning CS8629: Nullable value type may be null. // _ = (long)ni; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(long)ni").WithLocation(41, 17) ); } [Fact] public void NullableT_LongToStruct() { var source = @"struct S { public static implicit operator S(long l) => new S(); } class Program { // int -> long -> S -> S? static void F1(int i) { var s1 = (S?)i; _ = s1.Value; S? s2 = i; _ = s2.Value; int? ni = i; S? s3 = ni; _ = s3.Value; } // int? -> long? -> S? static void F2(int? ni) { if (ni.HasValue) { var s1 = (S?)ni; _ = s1.Value; S? s2 = ni; _ = s2.Value; } else { var s3 = (S?)ni; _ = s3.Value; // 1 S? s4 = ni; _ = s4.Value; // 2 } } // int? -> long? -> S? -> S static void F3(int? ni) { if (ni.HasValue) { _ = (S)ni; } else { _ = (S)ni; // 3 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17), // (45,20): warning CS8629: Nullable value type may be null. // _ = (S)ni; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(45, 20) ); } [Fact] public void NullableT_LongToNullableStruct() { var source = @"struct S { public static implicit operator S?(long l) => new S(); } class Program { // int -> long -> S? static void F1(int i) { var s1 = (S?)i; _ = s1.Value; // 1 S? s2 = i; _ = s2.Value; // 2 int? ni = i; S? s3 = ni; _ = s3.Value; // 3 } // int? -> long? -> S? static void F2(int? ni) { if (ni.HasValue) { var s1 = (S?)ni; _ = s1.Value; // 4 S? s2 = ni; _ = s2.Value; // 5 } else { var s3 = (S?)ni; _ = s3.Value; // 6 S? s4 = ni; _ = s4.Value; // 7 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(16, 13), // (24,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(24, 17), // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) ); } [Fact] public void NullableT_NullableLongToStruct() { var source = @"struct S { public static implicit operator S(long? l) => new S(); } class Program { // int -> int? -> long? -> S static void F1(int i) { _ = (S)i; S s = i; } // int? -> long? -> S static void F2(int? ni) { _ = (S)ni; S s = ni; } // int? -> long? -> S -> S? static void F3(int? ni) { var ns1 = (S?)ni; _ = ns1.Value; S? ns2 = ni; _ = ns1.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_NullableLongToNullableStruct() { var source = @"struct S { public static implicit operator S?(long? l) => new S(); } class Program { // int -> int? -> long? -> S static void F1(int i) { _ = (S)i; // 1 } // int? -> long? -> S? static void F2(int? ni) { if (ni.HasValue) { var ns1 = (S?)ni; _ = ns1.Value; // 2 S? ns2 = ni; _ = ns2.Value; // 3 } else { var ns3 = (S?)ni; _ = ns3.Value; // 4 S? ns4 = ni; _ = ns4.Value; // 5 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8629: Nullable value type may be null. // _ = (S)i; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(S)i").WithLocation(10, 13), // (18,17): warning CS8629: Nullable value type may be null. // _ = ns1.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns1").WithLocation(18, 17), // (20,17): warning CS8629: Nullable value type may be null. // _ = ns2.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns2").WithLocation(20, 17), // (25,17): warning CS8629: Nullable value type may be null. // _ = ns3.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns3").WithLocation(25, 17), // (27,17): warning CS8629: Nullable value type may be null. // _ = ns4.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ns4").WithLocation(27, 17) ); } [Fact] public void NullableT_StructToInt() { var source = @"struct S { public static implicit operator int(S s) => 0; } class Program { // S -> int -> long? static void F1(S s) { var nl1 = (long?)s; _ = nl1.Value; long? nl2 = s; _ = nl2.Value; } // S? -> int? -> long? static void F2(S? ns) { if (ns.HasValue) { var nl1 = (long?)ns; _ = nl1.Value; long? nl2 = ns; _ = nl2.Value; } else { var nl1 = (long?)ns; _ = nl1.Value; // 1 long? nl2 = ns; _ = nl2.Value; // 2 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (28,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(30, 17) ); } [Fact] public void NullableT_StructToNullableInt() { var source = @"struct S { public static implicit operator int?(S s) => 0; } class Program { // S -> int? -> long? static void F1(S s) { var nl1 = (long?)s; _ = nl1.Value; // 1 long? nl2 = s; _ = nl2.Value; // 2 } // S? -> int? -> long? static void F2(S? ns) { if (ns.HasValue) { var nl1 = (long?)ns; _ = nl1.Value; // 3 long? nl2 = ns; _ = nl2.Value; // 4 } else { var nl1 = (long?)ns; _ = nl1.Value; // 5 long? nl2 = ns; _ = nl2.Value; // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(30, 17) ); } [Fact] public void NullableT_NullableStructToInt() { var source = @"struct S { public static implicit operator int(S? s) => 0; } class Program { // S -> S? -> int -> long static void F1(S s) { _ = (long)s; long l2 = s; } // S? -> int -> long static void F2(S? ns) { if (ns.HasValue) { _ = (long)ns; long l2 = ns; } else { _ = (long)ns; long l2 = ns; } } // S? -> int -> long -> long? static void F3(S? ns) { if (ns.HasValue) { var nl1 = (long?)ns; _ = nl1.Value; long? nl2 = ns; _ = nl2.Value; } else { var nl1 = (long?)ns; _ = nl1.Value; long? nl2 = ns; _ = nl2.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_NullableStructToNullableInt() { var source = @"struct S { public static implicit operator int?(S? s) => 0; } class Program { // S -> S? -> int? -> long? static void F1(S s) { var nl1 = (long?)s; _ = nl1.Value; // 1 long? nl2 = s; _ = nl2.Value; // 2 } // S? -> int? -> long? static void F2(S? ns) { if (ns.HasValue) { var nl1 = (long?)ns; _ = nl1.Value; // 3 long? nl2 = ns; _ = nl2.Value; // 4 } else { var nl3 = (long?)ns; _ = nl3.Value; // 5 long? nl4 = ns; _ = nl4.Value; // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = nl1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = nl2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = nl3.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = nl4.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "nl4").WithLocation(30, 17) ); } [Fact] [WorkItem(35334, "https://github.com/dotnet/roslyn/issues/35334")] public void NullableT_StructToClass() { var source = @"struct S { public static implicit operator C(S s) => new C(); } class C { } class Program { // S -> C static void F1(S s) { var c1 = (C)s; _ = c1.ToString(); C c2 = s; _ = c2.ToString(); } // S? -> C? static void F2(S? ns) { if (ns.HasValue) { var c1 = (C?)ns; _ = c1.ToString(); // 1 C? c2 = ns; _ = c2.ToString(); } else { var c3 = (C?)ns; _ = c3.ToString(); // 2 C? c4 = ns; _ = c4.ToString(); // 3 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (24,17): warning CS8602: Dereference of a possibly null reference. // _ = c1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(24, 17), // (31,17): warning CS8602: Dereference of a possibly null reference. // _ = c3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(31, 17), // (33,17): warning CS8602: Dereference of a possibly null reference. // _ = c4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4").WithLocation(33, 17)); } [Fact] public void NullableT_StructToNullableClass() { var source = @"struct S { public static implicit operator C?(S s) => new C(); } class C { } class Program { // S -> C? static void F1(S s) { var c1 = (C?)s; _ = c1.ToString(); // 1 C? c2 = s; _ = c2.ToString(); // 2 } // S? -> C? static void F2(S? ns) { if (ns.HasValue) { var c1 = (C?)ns; _ = c1.ToString(); // 3 C? c2 = ns; _ = c2.ToString(); // 4 } else { var c3 = (C?)ns; _ = c3.ToString(); // 5 C? c4 = ns; _ = c4.ToString(); // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8602: Dereference of a possibly null reference. // _ = c1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(14, 13), // (16,13): warning CS8602: Dereference of a possibly null reference. // _ = c2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(16, 13), // (24,17): warning CS8602: Dereference of a possibly null reference. // _ = c1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(24, 17), // (26,17): warning CS8602: Dereference of a possibly null reference. // _ = c2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(26, 17), // (31,17): warning CS8602: Dereference of a possibly null reference. // _ = c3.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(31, 17), // (33,17): warning CS8602: Dereference of a possibly null reference. // _ = c4.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4").WithLocation(33, 17)); } [Fact] [WorkItem(35334, "https://github.com/dotnet/roslyn/issues/35334")] public void NullableT_NullableStructToClass() { var source = @"struct S { public static implicit operator C(S? s) => new C(); } class C { } class Program { // S -> C static void F1(S s) { var c1 = (C)s; _ = c1.ToString(); C c2 = s; _ = c2.ToString(); } // S? -> C? static void F2(S? ns) { if (ns.HasValue) { var c1 = (C?)ns; _ = c1.ToString(); // 1 C? c2 = ns; _ = c2.ToString(); } else { var c3 = (C?)ns; _ = c3.ToString(); // 2 C? c4 = ns; _ = c4.ToString(); } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (24,17): warning CS8602: Dereference of a possibly null reference. // _ = c1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(24, 17), // (31,17): warning CS8602: Dereference of a possibly null reference. // _ = c3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(31, 17)); } [Fact] public void NullableT_NullableStructToNullableClass() { var source = @"struct S { public static implicit operator C?(S? s) => new C(); } class C { } class Program { // S -> C? static void F1(S s) { var c1 = (C?)s; _ = c1.ToString(); // 1 C? c2 = s; _ = c2.ToString(); // 2 } // S? -> C? static void F2(S? ns) { if (ns.HasValue) { var c1 = (C?)ns; _ = c1.ToString(); // 3 C? c2 = ns; _ = c2.ToString(); // 4 } else { var c3 = (C?)ns; _ = c3.ToString(); // 5 C? c4 = ns; _ = c4.ToString(); // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8602: Dereference of a possibly null reference. // _ = c1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(14, 13), // (16,13): warning CS8602: Dereference of a possibly null reference. // _ = c2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(16, 13), // (24,17): warning CS8602: Dereference of a possibly null reference. // _ = c1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1").WithLocation(24, 17), // (26,17): warning CS8602: Dereference of a possibly null reference. // _ = c2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(26, 17), // (31,17): warning CS8602: Dereference of a possibly null reference. // _ = c3.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c3").WithLocation(31, 17), // (33,17): warning CS8602: Dereference of a possibly null reference. // _ = c4.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c4").WithLocation(33, 17)); } [Fact] public void NullableT_ClassToStruct() { var source = @"struct S { public static implicit operator S(C c) => new S(); } class C { } class Program { // C -> S static void F1(C c) { _ = (S)c; S s2 = c; } // C? -> S? static void F2(C? nc) { if (nc != null) { var s1 = (S?)nc; _ = s1.Value; S? s2 = nc; _ = s2.Value; } else { var s3 = (S?)nc; // 1 _ = s3.Value; S? s4 = nc; // 2 _ = s4.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (28,26): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S(C c)'. // var s3 = (S?)nc; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S(C c)").WithLocation(28, 26), // (30,21): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S(C c)'. // S? s4 = nc; // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S(C c)").WithLocation(30, 21)); } [Fact] public void NullableT_ClassToNullableStruct() { var source = @"struct S { public static implicit operator S?(C c) => new S(); } class C { } class Program { // C -> S? static void F1(C c) { var s1 = (S?)c; _ = s1.Value; // 1 S? s2 = c; _ = s2.Value; // 2 } // C? -> S? static void F2(C? nc) { if (nc != null) { var s1 = (S?)nc; _ = s1.Value; // 3 S? s2 = nc; _ = s2.Value; // 4 } else { var s3 = (S?)nc; // 5 _ = s3.Value; // 6 S? s4 = nc; // 7 _ = s4.Value; // 8 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(14, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(16, 13), // (24,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(24, 17), // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), // (30,26): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. // var s3 = (S?)nc; // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(30, 26), // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (32,21): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. // S? s4 = nc; // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(32, 21), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) ); } [Fact] public void NullableT_NullableClassToStruct() { var source = @"struct S { public static implicit operator S(C? c) => new S(); } class C { } class Program { // C -> S static void F1(C c) { _ = (S)c; S s2 = c; } // C? -> S? static void F2(C? nc) { if (nc != null) { var s1 = (S?)nc; _ = s1.Value; S? s2 = nc; _ = s2.Value; } else { var s3 = (S?)nc; _ = s3.Value; S? s4 = nc; _ = s4.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_NullableClassToNullableStruct() { var source = @"struct S { public static implicit operator S?(C? c) => new S(); } class C { } class Program { // C -> S? static void F1(C c) { var s1 = (S?)c; _ = s1.Value; // 1 S? s2 = c; _ = s2.Value; // 2 } // C? -> S? static void F2(C? nc) { if (nc != null) { var s1 = (S?)nc; _ = s1.Value; // 3 S? s2 = nc; _ = s2.Value; // 4 } else { var s3 = (S?)nc; _ = s3.Value; // 5 S? s4 = nc; _ = s4.Value; // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(14, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(16, 13), // (24,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(24, 17), // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), // (31,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), // (33,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) ); } // https://github.com/dotnet/roslyn/issues/31675: Add similar tests for // type parameters with `class?` constraint and Nullable constraint. [Fact] public void NullableT_StructToTypeParameterUnconstrained() { var source = @"struct S { public static implicit operator T(S s) => throw null!; } class C { // S -> T static void F1(S s) { var t1 = (T)s; _ = t1.ToString(); // 1 T t2 = s; _ = t2.ToString(); // 2 } // S? -> T static void F2(S? ns) { if (ns.HasValue) { var t1 = (T)ns; _ = t1.ToString(); // 3 } else { var t2 = (T)ns; // 4 _ = t2.ToString(); // 5 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8602: Dereference of a possibly null reference. // _ = t1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(11, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // _ = t2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(13, 13), // (21,17): warning CS8602: Dereference of a possibly null reference. // _ = t1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(21, 17), // (25,22): warning CS8601: Possible null reference assignment. // var t2 = (T)ns; // 4 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "(T)ns").WithLocation(25, 22), // (26,17): warning CS8602: Dereference of a possibly null reference. // _ = t2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(26, 17) ); } [Fact] public void NullableT_NullableStructToTypeParameterUnconstrained() { var source = @"struct S { public static implicit operator T(S? s) => throw null!; } class C { // S -> T static void F1(S s) { var t1 = (T)s; _ = t1.ToString(); // 1 T t2 = s; _ = t2.ToString(); // 2 } // S? -> T static void F2(S? ns) { if (ns.HasValue) { var t1 = (T)ns; _ = t1.ToString(); // 3 } else { var t2 = (T)ns; _ = t2.ToString(); // 4 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8602: Dereference of a possibly null reference. // _ = t1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(11, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // _ = t2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(13, 13), // (21,17): warning CS8602: Dereference of a possibly null reference. // _ = t1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(21, 17), // (26,17): warning CS8602: Dereference of a possibly null reference. // _ = t2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(26, 17)); } [Fact] [WorkItem(35334, "https://github.com/dotnet/roslyn/issues/35334")] public void NullableT_StructToTypeParameterClassConstraint() { var source = @"struct S { public static implicit operator T(S s) => throw null!; } class C where T : class { // S -> T static void F1(S s) { var t1 = (T)s; _ = t1.ToString(); T t2 = s; _ = t2.ToString(); } // S? -> T? static void F2(S? ns) { if (ns.HasValue) { var t1 = (T?)ns; _ = t1.ToString(); // 1 T? t2 = ns; _ = t2.ToString(); } else { var t3 = (T?)ns; _ = t3.ToString(); // 2 T? t4 = ns; _ = t4.ToString(); // 3 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (21,17): warning CS8602: Dereference of a possibly null reference. // _ = t1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(21, 17), // (28,17): warning CS8602: Dereference of a possibly null reference. // _ = t3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3").WithLocation(28, 17), // (30,17): warning CS8602: Dereference of a possibly null reference. // _ = t4.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4").WithLocation(30, 17)); } [Fact] [WorkItem(35334, "https://github.com/dotnet/roslyn/issues/35334")] public void NullableT_NullableStructToTypeParameterClassConstraint() { var source = @"struct S { public static implicit operator T(S? s) => throw null!; } class C where T : class { // S -> T static void F1(S s) { var t1 = (T)s; _ = t1.ToString(); T t2 = s; _ = t2.ToString(); } // S? -> T? static void F2(S? ns) { if (ns.HasValue) { var t1 = (T?)ns; _ = t1.ToString(); // 1 T? t2 = ns; _ = t2.ToString(); } else { var t3 = (T?)ns; _ = t3.ToString(); // 2 T? t4 = ns; _ = t4.ToString(); } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (21,17): warning CS8602: Dereference of a possibly null reference. // _ = t1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(21, 17), // (28,17): warning CS8602: Dereference of a possibly null reference. // _ = t3.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3").WithLocation(28, 17)); } [Fact] public void NullableT_StructToTypeParameterStructConstraint() { var source = @"struct S { public static implicit operator T(S s) => throw null!; } class C where T : struct { // S -> T static void F1(S s) { var t1 = (T)s; _ = t1.ToString(); T t2 = s; _ = t2.ToString(); } // S? -> T? static void F2(S? ns) { if (ns.HasValue) { var t1 = (T?)ns; _ = t1.Value; T? t2 = ns; _ = t2.Value; } else { var t3 = (T?)ns; _ = t3.Value; // 1 T? t4 = ns; _ = t4.Value; // 2 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (28,17): warning CS8629: Nullable value type may be null. // _ = t3.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = t4.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(30, 17) ); } [Fact] public void NullableT_NullableStructToTypeParameterStructConstraint() { var source = @"struct S { public static implicit operator T(S? s) => throw null!; } class C where T : struct { // S -> T static void F1(S s) { var t1 = (T)s; _ = t1.ToString(); T t2 = s; _ = t2.ToString(); } // S? -> T? static void F2(S? ns) { if (ns.HasValue) { var t1 = (T?)ns; _ = t1.Value; T? t2 = ns; _ = t2.Value; } else { var t3 = (T?)ns; _ = t3.Value; T? t4 = ns; _ = t4.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_StructToNullableTypeParameterStructConstraint() { var source = @"struct S where T : struct { public static implicit operator T?(S s) => throw null!; } class C where T : struct { // S -> T? static void F1(S s) { var t1 = (T?)s; _ = t1.Value; // 1 T? t2 = s; _ = t2.Value; // 2 } // S? -> T? static void F2(S? ns) { if (ns.HasValue) { var t1 = (T?)ns; _ = t1.Value; // 3 T? t2 = ns; _ = t2.Value; // 4 } else { var t3 = (T?)ns; // 5 _ = t3.Value; // 6 T? t4 = ns; // 7 _ = t4.Value; // 8 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = t3.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = t4.Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(30, 17) ); } [Fact] public void NullableT_NullableStructToNullableTypeParameterStructConstraint() { var source = @"struct S where T : struct { public static implicit operator T?(S? s) => throw null!; } class C where T : struct { // S -> T? static void F1(S s) { var t1 = (T?)s; _ = t1.Value; // 1 T? t2 = s; _ = t2.Value; // 2 } // S? -> T? static void F2(S? ns) { if (ns.HasValue) { var t1 = (T?)ns; _ = t1.Value; // 3 T? t2 = ns; _ = t2.Value; // 4 } else { var t3 = (T?)ns; _ = t3.Value; // 5 T? t4 = ns; _ = t4.Value; // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = t1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = t3.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = t4.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4").WithLocation(30, 17) ); } [Fact] public void NullableT_TypeParameterUnconstrainedToStruct() { var source = @"struct S { public static implicit operator S(T t) => throw null!; } class C { // T -> S static void F1(T t) { _ = (S)t; S s2 = t; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_TypeParameterUnconstrainedToNullableStruct() { var source = @"struct S { public static implicit operator S?(T t) => throw null!; } class C { // T -> S? static void F1(T t) { var s1 = (S?)t; _ = s1.Value; // 1 S? s2 = t; _ = s2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13) ); } [Fact] public void NullableT_TypeParameterClassConstraintToStruct() { var source = @"struct S { public static implicit operator S(T t) => throw null!; } class C where T : class { // T -> S static void F1(T t) { _ = (S)t; S s2 = t; } // T? -> S? static void F2(T? nt) { if (nt != null) { var s1 = (S?)nt; _ = s1.Value; S? s2 = nt; _ = s2.Value; } else { var s3 = (S?)nt; // 1 _ = s3.Value; S? s4 = nt; // 2 _ = s4.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (25,29): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S(T t)'. // var s3 = (S?)nt; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S(T t)").WithLocation(25, 29), // (27,24): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S(T t)'. // S? s4 = nt; // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S(T t)").WithLocation(27, 24)); } [Fact] public void NullableT_TypeParameterClassConstraintToNullableStruct() { var source = @"struct S { public static implicit operator S?(T t) => throw null!; } class C where T : class { // T -> S? static void F1(T t) { var s1 = (S?)t; _ = s1.Value; // 1 S? s2 = t; _ = s2.Value; // 2 } // T? -> S? static void F2(T? nt) { if (nt != null) { var s1 = (S?)nt; _ = s1.Value; // 3 S? s2 = nt; _ = s2.Value; // 4 } else { var s3 = (S?)nt; // 5 _ = s3.Value; // 6 S? s4 = nt; // 7 _ = s4.Value; // 8 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), // (27,29): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. // var s3 = (S?)nt; // 5 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(27, 29), // (28,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), // (29,24): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. // S? s4 = nt; // 7 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(29, 24), // (30,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) ); } [Fact] public void NullableT_TypeParameterStructConstraintToStruct() { var source = @"struct S { public static implicit operator S(T t) => throw null!; } class C where T : struct { // T -> S static void F1(T t) { _ = (S)t; S s2 = t; } // T? -> S? static void F2(T? nt) { if (nt != null) { var s1 = (S?)nt; _ = s1.Value; S? s2 = nt; _ = s2.Value; } else { var s3 = (S?)nt; _ = s3.Value; // 1 S? s4 = nt; _ = s4.Value; // 2 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (26,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(26, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(28, 17) ); } [Fact] public void NullableT_TypeParameterStructConstraintToNullableStruct() { var source = @"struct S { public static implicit operator S?(T t) => throw null!; } class C where T : struct { // T -> S? static void F1(T t) { var s1 = (S?)t; _ = s1.Value; // 1 S? s2 = t; _ = s2.Value; // 2 } // T? -> S? static void F2(T? nt) { if (nt != null) { var s1 = (S?)nt; _ = s1.Value; // 3 S? s2 = nt; _ = s2.Value; // 4 } else { var s3 = (S?)nt; // 5 _ = s3.Value; // 6 S? s4 = nt; // 7 _ = s4.Value; // 8 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) ); } [Fact] public void NullableT_NullableTypeParameterStructConstraintToStruct() { var source = @"struct S where T : struct { public static implicit operator S(T? t) => throw null!; } class C where T : struct { // T -> S static void F1(T t) { _ = (S)t; S s2 = t; } // T? -> S? static void F2(T? nt) { if (nt != null) { var s1 = (S?)nt; _ = s1.Value; S? s2 = nt; _ = s2.Value; } else { var s3 = (S?)nt; _ = s3.Value; S? s4 = nt; _ = s4.Value; } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_NullableTypeParameterStructConstraintToNullableStruct() { var source = @"struct S where T : struct { public static implicit operator S?(T? t) => throw null!; } class C where T : struct { // T -> S? static void F1(T t) { var s1 = (S?)t; _ = s1.Value; // 1 S? s2 = t; _ = s2.Value; // 2 } // T? -> S? static void F2(T? nt) { if (nt != null) { var s1 = (S?)nt; _ = s1.Value; // 3 S? s2 = nt; _ = s2.Value; // 4 } else { var s3 = (S?)nt; _ = s3.Value; // 5 S? s4 = nt; _ = s4.Value; // 6 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(11, 13), // (13,13): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(13, 13), // (21,17): warning CS8629: Nullable value type may be null. // _ = s1.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1").WithLocation(21, 17), // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), // (28,17): warning CS8629: Nullable value type may be null. // _ = s3.Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), // (30,17): warning CS8629: Nullable value type may be null. // _ = s4.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) ); } [Fact] public void NullableT_ValueTypeConstraint_01() { var source = @"abstract class A { internal abstract void F(U x) where U : T; } class B1 : A { internal override void F(U x) { int? y = x; _ = y.Value; _ = ((int?)x).Value; } } class B2 : A { internal override void F(U x) { int? y = x; _ = y.Value; // 1 _ = ((int?)x).Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // Conversions are not allowed from U to int in B1.F or from U to int? in B2.F, // so those conversions are not handled in NullableWalker either. comp.VerifyDiagnostics( // (9,18): error CS0029: Cannot implicitly convert type 'U' to 'int?' // int? y = x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("U", "int?").WithLocation(9, 18), // (11,14): error CS0030: Cannot convert type 'U' to 'int?' // _ = ((int?)x).Value; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int?)x").WithArguments("U", "int?").WithLocation(11, 14), // (18,18): error CS0029: Cannot implicitly convert type 'U' to 'int?' // int? y = x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("U", "int?").WithLocation(18, 18), // (19,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(19, 13), // (20,14): error CS0030: Cannot convert type 'U' to 'int?' // _ = ((int?)x).Value; // 2 Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int?)x").WithArguments("U", "int?").WithLocation(20, 14)); } [Fact] public void NullableT_ValueTypeConstraint_02() { var source = @"abstract class A { internal abstract void F(T t) where U : T; } class B1 : A { internal override void F(int? t) { U u = t; object? o = u; o.ToString(); // 1 } } class B2 : A { internal override void F(int? t) { if (t == null) return; U u = t; object? o = u; o.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,15): error CS0029: Cannot implicitly convert type 'int?' to 'U' // U u = t; Diagnostic(ErrorCode.ERR_NoImplicitConv, "t").WithArguments("int?", "U").WithLocation(9, 15), // (11,9): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(11, 9), // (19,15): error CS0029: Cannot implicitly convert type 'int?' to 'U' // U u = t; Diagnostic(ErrorCode.ERR_NoImplicitConv, "t").WithArguments("int?", "U").WithLocation(19, 15)); } [Fact] public void NullableT_ValueTypeConstraint_03() { var source = @"abstract class A { internal abstract void F(T t) where U : T; } class B1 : A { internal override void F(int? t) { U u = (U)(object?)t; object? o = u; o.ToString(); // 1 } } class B2 : A { internal override void F(int? t) { if (t == null) return; U u = (U)(object?)t; object? o = u; o.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,9): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(11, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // o.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(21, 9)); } [Fact] public void NullableT_Box() { var source = @"class Program { static void F1(T? x1, T? y1) where T : struct { if (x1 == null) return; ((object?)x1).ToString(); // 1 ((object?)y1).ToString(); // 2 } static void F2(T? x2, T? y2) where T : struct { if (x2 == null) return; object? z2 = x2; z2.ToString(); object? w2 = y2; w2.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,10): warning CS8602: Dereference of a possibly null reference. // ((object?)x1).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x1").WithLocation(6, 10), // (7,10): warning CS8602: Dereference of a possibly null reference. // ((object?)y1).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)y1").WithLocation(7, 10), // (15,9): warning CS8602: Dereference of a possibly null reference. // w2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(15, 9) ); } [Fact] public void NullableT_Box_ValueTypeConstraint() { var source = @"abstract class A { internal abstract void F(U x) where U : T; } class B1 : A { internal override void F(U x) { ((object?)x).ToString(); // 1 object y = x; y.ToString(); } } class B2 : A { internal override void F(U x) { ((object?)x).ToString(); // 2 object? y = x; y.ToString(); } void F(int? x) { ((object?)x).ToString(); // 3 object? y = x; y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,10): warning CS8602: Dereference of a possibly null reference. // ((object?)x).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x").WithLocation(9, 10), // (18,10): warning CS8602: Dereference of a possibly null reference. // ((object?)x).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x").WithLocation(18, 10), // (25,10): warning CS8602: Dereference of a possibly null reference. // ((object?)x).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object?)x").WithLocation(25, 10) ); } [Fact] public void NullableT_Unbox() { var source = @"class Program { static void F1(object x1, object? y1) where T : struct { _ = ((T?)x1).Value; _ = ((T?)y1).Value; // 1 } static void F2(object x2, object? y2) where T : struct { var z2 = (T?)x2; _ = z2.Value; var w2 = (T?)y2; _ = w2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,14): warning CS8629: Nullable value type may be null. // _ = ((T?)y1).Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T?)y1").WithLocation(6, 14), // (13,13): warning CS8629: Nullable value type may be null. // _ = w2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w2").WithLocation(13, 13) ); } [Fact] public void NullableT_Unbox_ValueTypeConstraint() { var source = @"abstract class A { internal abstract void F(object? x) where U : T; } class B1 : A { internal override void F(object? x) { int y = (U)x; } } class B2 : A { internal override void F(object? x) { _ = ((U)x).Value; _ = ((int?)(object)(U)x).Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // Conversions are not allowed from U to int in B1.F or from U to int? in B2.F, // so those conversions are not handled in NullableWalker either. comp.VerifyDiagnostics( // (9,17): error CS0029: Cannot implicitly convert type 'U' to 'int' // int y = (U)x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "(U)x").WithArguments("U", "int").WithLocation(9, 17), // (9,17): warning CS8605: Unboxing a possibly null value. // int y = (U)x; Diagnostic(ErrorCode.WRN_UnboxPossibleNull, "(U)x").WithLocation(9, 17), // (16,20): error CS1061: 'U' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'U' could be found (are you missing a using directive or an assembly reference?) // _ = ((U)x).Value; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Value").WithArguments("U", "Value").WithLocation(16, 20), // (17,14): warning CS8629: Nullable value type may be null. // _ = ((int?)(object)(U)x).Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int?)(object)(U)x").WithLocation(17, 14), // (17,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // _ = ((int?)(object)(U)x).Value; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(object)(U)x").WithLocation(17, 20)); } [Fact] public void NullableT_Dynamic() { var source = @"class Program { static void F1(dynamic x1, dynamic? y1) where T : struct { T? z1 = x1; _ = z1.Value; T? w1 = y1; _ = w1.Value; // 1 } static void F2(dynamic x2, dynamic? y2) where T : struct { var z2 = (T?)x2; _ = z2.Value; var w2 = (T?)y2; _ = w2.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = w1.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w1").WithLocation(8, 13), // (15,13): warning CS8629: Nullable value type may be null. // _ = w2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "w2").WithLocation(15, 13) ); } [Fact] public void NullableT_23() { var source = @"#pragma warning disable 649 struct S { internal int F; } class Program { static void F(S? x, S? y) { if (y == null) return; int? ni; ni = x?.F; _ = ni.Value; // 1 ni = y?.F; _ = ni.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8629: Nullable value type may be null. // _ = ni.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(13, 13), // (15,13): warning CS8629: Nullable value type may be null. // _ = ni.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "ni").WithLocation(15, 13) ); } [Fact] public void NullableT_24() { var source = @"class Program { static void F(bool b, int? x, int? y) { if ((b ? x : y).HasValue) { _ = x.Value; // 1 _ = y.Value; // 2 } if ((b ? x : x).HasValue) { _ = x.Value; // 3 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,17): warning CS8629: Nullable value type may be null. // _ = x.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(7, 17), // (8,17): warning CS8629: Nullable value type may be null. // _ = y.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(8, 17), // (12,17): warning CS8629: Nullable value type may be null. // _ = x.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(12, 17) ); } [Fact] public void NullableT_25() { var source = @"class Program { static void F1(int? x) { var y = ~x; _ = y.Value; // 1 } static void F2(int x, int? y) { var z = x + y; _ = z.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(6, 13), // (11,13): warning CS8629: Nullable value type may be null. // _ = z.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(11, 13) ); } [WorkItem(31500, "https://github.com/dotnet/roslyn/issues/31500")] [Fact] public void NullableT_26() { var source = @"class Program { static void F1(int? x) { if (x == null) return; var y = ~x; _ = y.Value; } static void F2(int x, int? y) { if (y == null) return; var z = x + y; _ = z.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [WorkItem(31500, "https://github.com/dotnet/roslyn/issues/31500")] [Fact] public void NullableT_27() { var source = @"struct A { public static implicit operator B(A a) => new B(); } struct B { } class Program { static void F1(A? a) { B? b = a; _ = b.Value; // 1 } static void F2(A? a) { if (a != null) { B? b1 = a; _ = b1.Value; } else { B? b2 = a; _ = b2.Value; // 2 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8629: Nullable value type may be null. // _ = b.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b").WithLocation(13, 13), // (25,17): warning CS8629: Nullable value type may be null. // _ = b2.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b2").WithLocation(25, 17) ); } [Fact] public void NullableT_28() { var source = @"class Program { static void F(T? x, T? y) where T : struct { object z = x ?? y; object? w = x ?? y; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object z = x ?? y; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x ?? y").WithLocation(5, 20)); } [Fact] public void NullableT_29() { var source = @"class Program { static void F(T? t) where T : struct { if (!t.HasValue) return; _ = t ?? default(T); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( ); } [Fact] public void NullableT_30() { var source = @"class Program { static void F(T? t) where T : struct { t.HasValue = true; t.Value = default(T); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS0200: Property or indexer 'T?.HasValue' cannot be assigned to -- it is read only // t.HasValue = true; Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "t.HasValue").WithArguments("T?.HasValue").WithLocation(5, 9), // (6,9): error CS0200: Property or indexer 'T?.Value' cannot be assigned to -- it is read only // t.Value = default(T); Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "t.Value").WithArguments("T?.Value").WithLocation(6, 9), // (6,9): warning CS8629: Nullable value type may be null. // t.Value = default(T); Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(6, 9) ); } [Fact] public void NullableT_31() { var source = @"struct S { } class Program { static void F() { var s = (S?)F; _ = s.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,18): error CS0030: Cannot convert type 'method' to 'S?' // var s = (S?)F; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(S?)F").WithArguments("method", "S?").WithLocation(6, 18)); } [WorkItem(33330, "https://github.com/dotnet/roslyn/issues/33330")] [Fact] public void NullableT_32() { var source = @"#nullable enable class Program { static void F(int? i, int j) { _ = (int)(i & j); // 1 _ = (int)(i | j); // 2 _ = (int)(i ^ j); // 3 _ = (int)(~i); // 4 if (i.HasValue) { _ = (int)(i & j); _ = (int)(i | j); _ = (int)(i ^ j); _ = (int)(~i); } } static void F(bool? i, bool b) { _ = (bool)(i & b); // 5 _ = (bool)(i | b); // 6 _ = (bool)(i ^ b); // 7 _ = (bool)(!i); // 8 if (i.HasValue) { _ = (bool)(i & b); _ = (bool)(i | b); _ = (bool)(i ^ b); _ = (bool)(!i); } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8629: Nullable value type may be null. // _ = (int)(i & j); // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int)(i & j)").WithLocation(6, 13), // (7,13): warning CS8629: Nullable value type may be null. // _ = (int)(i | j); // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int)(i | j)").WithLocation(7, 13), // (8,13): warning CS8629: Nullable value type may be null. // _ = (int)(i ^ j); // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int)(i ^ j)").WithLocation(8, 13), // (9,13): warning CS8629: Nullable value type may be null. // _ = (int)(~i); // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(int)(~i)").WithLocation(9, 13), // (20,13): warning CS8629: Nullable value type may be null. // _ = (bool)(i & b); // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(bool)(i & b)").WithLocation(20, 13), // (21,13): warning CS8629: Nullable value type may be null. // _ = (bool)(i | b); // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(bool)(i | b)").WithLocation(21, 13), // (22,13): warning CS8629: Nullable value type may be null. // _ = (bool)(i ^ b); // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(bool)(i ^ b)").WithLocation(22, 13), // (23,13): warning CS8629: Nullable value type may be null. // _ = (bool)(!i); // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(bool)(!i)").WithLocation(23, 13)); } [WorkItem(32626, "https://github.com/dotnet/roslyn/issues/32626")] [Fact] public void NullableCtor() { var source = @" using System; struct S { internal object? F; } class Program { static void Baseline() { S? x = new S(); x.Value.F.ToString(); // warning baseline S? y = new S() { F = 2 }; y.Value.F.ToString(); // ok baseline } static void F() { S? x = new Nullable(new S()); x.Value.F.ToString(); // warning S? y = new Nullable(new S() { F = 2 }); y.Value.F.ToString(); // ok } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // x.Value.F.ToString(); // warning baseline Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(14, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // x.Value.F.ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(23, 9) ); } [WorkItem(32626, "https://github.com/dotnet/roslyn/issues/32626")] [Fact] public void NullableCtorErr() { var source = @" using System; struct S { internal object? F; } class Program { static void F() { S? x = new S() { F = 2 }; x.Value.F.ToString(); // ok baseline S? y = new Nullable(1); y.Value.F.ToString(); // warning 1 S? z = new Nullable(null); z.Value.F.ToString(); // warning 2 } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,32): error CS1503: Argument 1: cannot convert from 'int' to 'S' // S? y = new Nullable(1); Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "S").WithLocation(16, 32), // (17,9): warning CS8602: Dereference of a possibly null reference. // y.Value.F.ToString(); // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.F").WithLocation(17, 9), // (19,32): error CS1503: Argument 1: cannot convert from '' to 'S' // S? z = new Nullable(null); Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "", "S").WithLocation(19, 32), // (20,9): warning CS8602: Dereference of a possibly null reference. // z.Value.F.ToString(); // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Value.F").WithLocation(20, 9) ); } [WorkItem(32626, "https://github.com/dotnet/roslyn/issues/32626")] [Fact] public void NullableCtor1() { var source = @" using System; struct S { internal object? F; } class Program { static void F() { S? x = new Nullable(new S() { F = 2 }); x.Value.F.ToString(); // ok S? y = new Nullable(); y.Value.F.ToString(); // warning 1 S? z = new Nullable(default); z.Value.F.ToString(); // warning 2 } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,9): warning CS8629: Nullable value type may be null. // y.Value.F.ToString(); // warning 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(17, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // y.Value.F.ToString(); // warning 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.F").WithLocation(17, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // z.Value.F.ToString(); // warning 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Value.F").WithLocation(20, 9)); } [Fact] public void NullableT_AlwaysTrueOrFalse() { var source = @"class Program { static void F1(T? t1) where T : struct { if (!t1.HasValue) return; if (t1.HasValue) { } // always false if (!t1.HasValue) { } // always true if (t1 != null) { } // always false if (t1 == null) { } // always true } static void F2(T? t2) where T : struct { if (!t2.HasValue) return; if (t2 == null) { } // always false if (t2 != null) { } // always true if (!t2.HasValue) { } // always false if (t2.HasValue) { } // always true } static void F3(T? t3) where T : struct { if (t3 == null) return; if (!t3.HasValue) { } // always true if (t3.HasValue) { } // always false if (t3 == null) { } // always true if (t3 != null) { } // always false } static void F4(T? t4) where T : struct { if (t4 == null) return; if (t4 != null) { } // always true if (t4 == null) { } // always false if (t4.HasValue) { } // always true if (!t4.HasValue) { } // always false } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_As_01() { var source = @"class Program { static void F1(object x1, object? y1) where T : struct { _ = (x1 as T?).Value; // 1 _ = (y1 as T?).Value; // 2 } static void F2(T x2, T? y2) where T : struct { _ = (x2 as T?).Value; _ = (y2 as T?).Value; // 3 } static void F3(U x3) where T : struct { _ = (x3 as T?).Value; // 4 } static void F4(U x4, U? y4) where T : struct where U : class { _ = (x4 as T?).Value; // 5 _ = (y4 as T?).Value; // 6 } static void F5(U x5, U? y5) where T : struct where U : struct { _ = (x5 as T?).Value; // 7 _ = (y5 as T?).Value; // 8 } static void F6(U x6) where T : struct, U { _ = (x6 as T?).Value; // 9 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,14): warning CS8629: Nullable value type may be null. // _ = (x1 as T?).Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x1 as T?").WithLocation(5, 14), // (6,14): warning CS8629: Nullable value type may be null. // _ = (y1 as T?).Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y1 as T?").WithLocation(6, 14), // (11,14): warning CS8629: Nullable value type may be null. // _ = (y2 as T?).Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y2 as T?").WithLocation(11, 14), // (15,14): warning CS8629: Nullable value type may be null. // _ = (x3 as T?).Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x3 as T?").WithLocation(15, 14), // (19,14): warning CS8629: Nullable value type may be null. // _ = (x4 as T?).Value; // 5 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x4 as T?").WithLocation(19, 14), // (20,14): warning CS8629: Nullable value type may be null. // _ = (y4 as T?).Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y4 as T?").WithLocation(20, 14), // (24,14): warning CS8629: Nullable value type may be null. // _ = (x5 as T?).Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x5 as T?").WithLocation(24, 14), // (25,14): warning CS8629: Nullable value type may be null. // _ = (y5 as T?).Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y5 as T?").WithLocation(25, 14), // (29,14): warning CS8629: Nullable value type may be null. // _ = (x6 as T?).Value; // 9 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x6 as T?").WithLocation(29, 14) ); } [Fact] public void NullableT_As_02() { var source = @"class Program { static void F1(T? t1) where T : struct { _ = (t1 as object).ToString(); // 1 if (t1.HasValue) _ = (t1 as object).ToString(); else _ = (t1 as object).ToString(); // 2 } static void F2(T? t2) where T : struct { _ = (t2 as T?).Value; // 3 if (t2.HasValue) _ = (t2 as T?).Value; else _ = (t2 as T?).Value; // 4 } static void F3(T? t3) where T : struct where U : class { _ = (t3 as U).ToString(); // 5 if (t3.HasValue) _ = (t3 as U).ToString(); // 6 else _ = (t3 as U).ToString(); // 7 } static void F4(T? t4) where T : struct where U : struct { _ = (t4 as U?).Value; // 8 if (t4.HasValue) _ = (t4 as U?).Value; // 9 else _ = (t4 as U?).Value; // 10 } static void F5(T? t5) where T : struct { _ = (t5 as dynamic).ToString(); // 11 if (t5.HasValue) _ = (t5 as dynamic).ToString(); else _ = (t5 as dynamic).ToString(); // 12 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,14): warning CS8602: Dereference of a possibly null reference. // _ = (t1 as object).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1 as object").WithLocation(5, 14), // (9,18): warning CS8602: Dereference of a possibly null reference. // _ = (t1 as object).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1 as object").WithLocation(9, 18), // (13,14): warning CS8629: Nullable value type may be null. // _ = (t2 as T?).Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2 as T?").WithLocation(13, 14), // (17,18): warning CS8629: Nullable value type may be null. // _ = (t2 as T?).Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2 as T?").WithLocation(17, 18), // (21,14): warning CS8602: Dereference of a possibly null reference. // _ = (t3 as U).ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3 as U").WithLocation(21, 14), // (23,18): warning CS8602: Dereference of a possibly null reference. // _ = (t3 as U).ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3 as U").WithLocation(23, 18), // (25,18): warning CS8602: Dereference of a possibly null reference. // _ = (t3 as U).ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3 as U").WithLocation(25, 18), // (29,14): warning CS8629: Nullable value type may be null. // _ = (t4 as U?).Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4 as U?").WithLocation(29, 14), // (31,18): warning CS8629: Nullable value type may be null. // _ = (t4 as U?).Value; // 9 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4 as U?").WithLocation(31, 18), // (33,18): warning CS8629: Nullable value type may be null. // _ = (t4 as U?).Value; // 10 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t4 as U?").WithLocation(33, 18), // (37,14): warning CS8602: Dereference of a possibly null reference. // _ = (t5 as dynamic).ToString(); // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5 as dynamic").WithLocation(37, 14), // (41,18): warning CS8602: Dereference of a possibly null reference. // _ = (t5 as dynamic).ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5 as dynamic").WithLocation(41, 18) ); } [Fact] public void NullableT_As_ValueTypeConstraint_01() { var source = @"abstract class A { internal abstract void F(U u) where U : T; } class B1 : A { internal override void F(U u) { _ = (u as U?).Value; _ = (u as int?).Value; // 1 } } class B2 : A { internal override void F(U u) { _ = (u as int?).Value; // 2 } }"; // Implicit conversions are not allowed from U to int in B1.F or from U to int? in B2.F, // so those conversions are not handled in NullableWalker either. var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,14): warning CS8629: Nullable value type may be null. // _ = (u as int?).Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u as int?").WithLocation(10, 14), // (17,14): warning CS8629: Nullable value type may be null. // _ = (u as int?).Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "u as int?").WithLocation(17, 14) ); } [Fact] public void NullableT_As_ValueTypeConstraint_02() { var source = @"abstract class A { internal abstract void F(T t) where U : T; } class B1 : A { internal override void F(int t) { _ = (t as U?).Value; // 1 } } class B2 : A { internal override void F(int? t) { _ = (t as U).Value; // 2 _ = (t as U?).Value; // 3 } }"; // Implicit conversions are not allowed from int to U in B1.F or from int? to U in B2.F, // so those conversions are not handled in NullableWalker either. var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,14): warning CS8629: Nullable value type may be null. // _ = (t as U?).Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t as U?").WithLocation(9, 14), // (16,14): error CS0413: The type parameter 'U' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint // _ = (t as U).Value; // 2 Diagnostic(ErrorCode.ERR_AsWithTypeVar, "t as U").WithArguments("U").WithLocation(16, 14), // (17,14): warning CS8629: Nullable value type may be null. // _ = (t as U?).Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t as U?").WithLocation(17, 14), // (17,19): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // _ = (t as U?).Value; // 3 Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "U?").WithArguments("System.Nullable", "T", "U").WithLocation(17, 19) ); } [WorkItem(31501, "https://github.com/dotnet/roslyn/issues/31501")] [Fact] public void NullableT_Suppress_01() { var source = @"class Program { static void F(T x, T? y, T? z) where T : struct { _ = (T)((T?)null)!; _ = (T)((T?)default)!; _ = (T)default(T?)!; _ = (T)((T?)x)!; _ = (T)y!; _ = (T)y!!; _ = ((T)z)!; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,14): warning CS8629: Nullable value type may be null. // _ = ((T)z)!; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "(T)z").WithLocation(11, 14)); } [WorkItem(31501, "https://github.com/dotnet/roslyn/issues/31501")] [Fact] public void NullableT_Suppress_02() { var source = @"class Program { static void F(T x, T? y, T? z) where T : struct { _ = ((T?)null)!.Value; _ = ((T?)default)!.Value; _ = default(T?)!.Value; _ = ((T?)x)!.Value; _ = y!.Value; _ = y!!.Value; _ = z.Value!; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = z.Value!; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(11, 13) ); } [Fact] public void NullableT_NotNullWhenTrue() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static bool F([NotNullWhen(true)]T? t) where T : struct { return true; } static void G(T? t) where T : struct { if (F(t)) _ = t.Value; else _ = t.Value; // 1 } }"; var comp = CreateCompilation(new[] { source, NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,17): warning CS8629: Nullable value type may be null. // _ = t.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(13, 17) ); } [Fact] public void NullableT_AssertsTrue() { var source = @"using System.Diagnostics.CodeAnalysis; class Program { static void F([AssertsTrue] bool b) { } static void G(T? x, T? y) where T : struct { F(x != null); _ = x.Value; F(y.HasValue); _ = y.Value; } }"; var comp = CreateCompilation(new[] { source, AssertsTrueAttributeDefinition }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void NullableT_AllMembers() { var source = @"class C where T : struct { static void F1(T? t1) { _ = t1.HasValue; } static void F2(T? t2) { _ = t2.Value; // 1 } static void F3(T? t3) { _ = t3.GetValueOrDefault(); } static void F4(T? t4) { _ = t4.GetHashCode(); } static void F5(T? t5) { _ = t5.ToString(); } static void F6(T? t6) { _ = t6.Equals(t6); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): warning CS8629: Nullable value type may be null. // _ = t2.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t2").WithLocation(9, 13) ); } [WorkItem(33174, "https://github.com/dotnet/roslyn/issues/33174")] [Fact] public void NullableBaseMembers() { var source = @" static class Program { static void Main() { int? x = null; x.GetHashCode(); // ok x.Extension(); // ok x.GetType(); // warning1 int? y = null; y.MemberwiseClone(); // warning2 y.Lalala(); // does not exist } static void Extension(this int? self) { } } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8629: Nullable value type may be null. // x.GetType(); // warning1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(12, 9), // (15,9): warning CS8629: Nullable value type may be null. // y.MemberwiseClone(); // warning2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(15, 9), // (15,11): error CS1540: Cannot access protected member 'object.MemberwiseClone()' via a qualifier of type 'int?'; the qualifier must be of type 'Program' (or derived from it) // y.MemberwiseClone(); // warning2 Diagnostic(ErrorCode.ERR_BadProtectedAccess, "MemberwiseClone").WithArguments("object.MemberwiseClone()", "int?", "Program").WithLocation(15, 11), // (17,11): error CS1061: 'int?' does not contain a definition for 'Lalala' and no accessible extension method 'Lalala' accepting a first argument of type 'int?' could be found (are you missing a using directive or an assembly reference?) // y.Lalala(); // does not exist Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Lalala").WithArguments("int?", "Lalala").WithLocation(17, 11) ); } [Fact] public void NullableT_Using() { var source = @"using System; struct S : IDisposable { void IDisposable.Dispose() { } } class Program { static void F1(S? s) { using (s) { } _ = s.Value; // 1 } static void F2(T? t) where T : struct, IDisposable { using (t) { } _ = t.Value; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,13): warning CS8629: Nullable value type may be null. // _ = s.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(11, 13), // (16,13): warning CS8629: Nullable value type may be null. // _ = t.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(16, 13) ); } [WorkItem(31503, "https://github.com/dotnet/roslyn/issues/31503")] [Fact] public void NullableT_ForEach() { var source = @"using System.Collections; using System.Collections.Generic; struct S : IEnumerable { public IEnumerator GetEnumerator() => throw null!; } class Program { static void F1(S? s) { foreach (var i in s) // 1 ; foreach (var i in s) ; } static void F2(T? t) where T : struct, IEnumerable { foreach (var i in t) // 2 ; foreach (var i in t) ; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,27): warning CS8629: Nullable value type may be null. // foreach (var i in s) // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(11, 27), // (18,27): warning CS8629: Nullable value type may be null. // foreach (var i in t) // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t").WithLocation(18, 27) ); } [Fact] public void NullableT_IndexAndRange() { var source = @"class Program { static void F1(int? x) { _ = ^x; } static void F2(int? y) { _ = ..y; _ = ^y..; } static void F3(int? z, int? w) { _ = z..^w; } }"; var comp = CreateCompilationWithIndexAndRange(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [WorkItem(31770, "https://github.com/dotnet/roslyn/issues/31770")] [Fact] public void UserDefinedConversion_NestedNullability_01() { var source = @"class A { } class B { public static implicit operator B(A a) => throw null!; } class Program { static void F(B b) { } static void Main() { A a = new A(); B b = a; // 1 F(a); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/31798: Consider improving warning to reference user-defined operator. comp.VerifyDiagnostics( // (12,15): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // B b = a; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "a").WithArguments("A", "A").WithLocation(12, 15), // (13,11): warning CS8620: Nullability of reference types in argument of type 'A' doesn't match target type 'A' for parameter 'b' in 'void Program.F(B b)'. // F(a); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "a").WithArguments("A", "A", "b", "void Program.F(B b)").WithLocation(13, 11)); } [Fact] public void UserDefinedConversion_NestedNullability_02() { var source = @"class A { } class B { public static implicit operator A(B b) => throw null!; } class Program { static void F(A a) { } static void Main() { B b = new B(); A a = b; // 1 F(b); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/31798: Consider improving warning to reference user-defined operator. comp.VerifyDiagnostics( // (12,24): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // A a = b; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "b").WithArguments("A", "A").WithLocation(12, 24), // (13,11): warning CS8620: Nullability of reference types in argument of type 'A' doesn't match target type 'A' for parameter 'a' in 'void Program.F(A a)'. // F(b); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b").WithArguments("A", "A", "a", "void Program.F(A a)").WithLocation(13, 11)); } [WorkItem(31864, "https://github.com/dotnet/roslyn/issues/31864")] [Fact] public void BestType_DifferentTupleNullability_01() { var source = @"using System; class Program { static void F(bool b) { DateTime? x = DateTime.MaxValue; string? y = null; _ = (b ? (x, y) : (null, null))/*T:(System.DateTime?, string?)*/; _ = (b ? (null, null) : (x, y))/*T:(System.DateTime?, string?)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(31864, "https://github.com/dotnet/roslyn/issues/31864")] [Fact] public void BestType_DifferentTupleNullability_02() { var source = @"class Program { static void F(bool b) where T : class, new() where U : struct { T? t1 = null; T? t2 = new T(); U? u1 = null; U? u2 = new U(); _ = (b ? (t1, t2) : (null, null))/*T:(T?, T?)*/; _ = (b ? (null, null) : (u1, u2))/*T:(U?, U?)*/; _ = (b ? (t1, u2) : (null, null))/*T:(T?, U?)*/; _ = (b ? (null, null) : (t2, u1))/*T:(T?, U?)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(31864, "https://github.com/dotnet/roslyn/issues/31864")] [Fact] public void BestType_DifferentTupleNullability_03() { var source = @"class Program { static void F() where T : class, new() where U : struct { T? t1 = null; T? t2 = new T(); U? u1 = null; U? u2 = new U(); _ = new[] { (t1, t2), (null, null) }[0]/*T:(T?, T?)*/; _ = new[] { (null, null), (u1, u2) }[0]/*T:(U?, U?)*/; _ = new[] { (t1, u2), (null, null) }[0]/*T:(T?, U?)*/; _ = new[] { (null, null), (t2, u1) }[0]/*T:(T?, U?)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_04() { var source = @"class Program { static void F(bool b) where T : class, new() { _ = (b ? (new T(), new T()) : (null, null))/*T:(T?, T?)*/; _ = (b ? (null, new T()) : (new T(), new T()))/*T:(T?, T!)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_05() { var source = @"class Program { static void F() where T : class, new() { _ = new[] { (new T(), new T()), (null, null) }[0]/*T:(T?, T?)*/; _ = new[] { (null, new T()), (new T(), new T()) }[0]/*T:(T?, T!)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_06() { var source = @"class Program { static void F(bool b, T x, T? y) where T : class { _ = (b ? (x, y) : (y, x))/*T:(T?, T?)*/; _ = (b ? (x, x) : (y, default))/*T:(T?, T?)*/; _ = (b ? (null, x) : (x, y))/*T:(T?, T?)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_07() { var source = @"class Program { static void F(T x, T? y) where T : class { _ = new[] { (x, y), (y, x) }[0]/*T:(T?, T?)*/; _ = new[] { (x, x), (y, default) }[0]/*T:(T?, T?)*/; _ = new[] { (null, x), (x, y) }[0]/*T:(T?, T?)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_08() { var source = @"class Program { static void F(bool b, T? x, object y) where T : class { var t = (b ? (x: y, y: y) : (x, null))/*T:(object? x, object?)*/; var u = (b ? (x: default, y: x) : (x, y))/*T:(T? x, object? y)*/; t.x.ToString(); // 1 t.y.ToString(); // 2 u.x.ToString(); // 3 u.y.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.x").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.x").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.y.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(11, 9)); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_09() { var source = @"class Program { static void F(T? x, object y) where T : class { var t = new[] { (x: y, y: y), (x, null) }[0]/*T:(object? x, object?)*/; var u = new[] { (x: default, y: x), (x, y) }[0]/*T:(T? x, object? y)*/; t.x.ToString(); // 1 t.y.ToString(); // 2 u.x.ToString(); // 3 u.y.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // t.x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.x").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // t.y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.y").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // u.x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.x").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.y.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u.y").WithLocation(11, 9)); comp.VerifyTypes(); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33344")] [WorkItem(32575, "https://github.com/dotnet/roslyn/issues/32575")] public void BestType_DifferentTupleNullability_10() { var source = @"class Program { static void F(bool b, T t, U u) where U : class { var x = (b ? (t, u) : default)/*T:(T t, U? u)*/; x.Item1.ToString(); // 1 x.Item2.ToString(); // 2 var y = (b ? default : (t, u))/*T:(T t, U? u)*/; y.Item1.ToString(); // 3 y.Item2.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32575: Not handling default for U. comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item1").WithLocation(7, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // x.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item2").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // y.Item1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(10, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // y.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item2").WithLocation(11, 9) ); comp.VerifyTypes(); } [Fact] [WorkItem(32575, "https://github.com/dotnet/roslyn/issues/32575")] [WorkItem(33344, "https://github.com/dotnet/roslyn/issues/33344")] public void BestType_DifferentTupleNullability_11() { var source = @"class Program { static void F(T t, U u) where U : class { var x = new[] { (t, u), default }[0]/*T:(T t, U u)*/; // should be (T t, U? u) x.Item1.ToString(); // 1 x.Item2.ToString(); // 2 var y = new[] { default, (t, u) }[0]/*T:(T t, U u)*/; // should be (T t, U? u) y.Item1.ToString(); // 3 y.Item2.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // https://github.com/dotnet/roslyn/issues/32575: Not handling default for U. // SHOULD BE 4 diagnostics. ); comp.VerifyTypes(); } [Fact] public void BestType_DifferentTupleNullability_12() { var source = @"class Program { static void F(bool b, U? u) where U : struct { var t = b ? (1, u) : default; t.Item1.ToString(); _ = t.Item2.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(8, 13) ); } [Fact] public void BestType_DifferentTupleNullability_13() { var source = @"class Program { static void F(U? u) where U : struct { var t = new[] { (1, u), default }[0]; t.Item1.ToString(); _ = t.Item2.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = t.Item2.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "t.Item2").WithLocation(8, 13) ); } [WorkItem(32006, "https://github.com/dotnet/roslyn/issues/32006")] [Fact(Skip = "https://github.com/dotnet/roslyn/issues/32006")] public void LambaReturnType_DifferentTupleNullability_01() { // See https://github.com/dotnet/roslyn/issues/32006 // need to relax assertion in GetImplicitTupleLiteralConversion var source = @"using System; class Program { static T F(Func f) { return f(true); } static void G() where T : class, new() where U : struct { F(b => { if (b) { T? t1 = null; U? u2 = new U(); return (t1, u2); } return (null, null); })/*T:(T? t1, U? u2)*/; F(b => { if (b) return (null, null); T? t2 = new T(); U? u1 = null; return (t2, u1); })/*T:(T! t2, U? u1)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32006: Warning inferring return type. comp.VerifyDiagnostics( // (20,24): warning CS8619: Nullability of reference types in value of type '(T?, U?)' doesn't match target type '(T? t1, U? u2)'. // return (null, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, null)").WithArguments("(T?, U?)", "(T? t1, U? u2)").WithLocation(20, 24), // (24,31): warning CS8619: Nullability of reference types in value of type '(T?, U?)' doesn't match target type '(T t2, U? u1)'. // if (b) return (null, null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, null)").WithArguments("(T?, U?)", "(T t2, U? u1)").WithLocation(24, 31)); comp.VerifyTypes(); } [WorkItem(32006, "https://github.com/dotnet/roslyn/issues/32006")] [Fact(Skip = "https://github.com/dotnet/roslyn/issues/32006")] public void LambaReturnType_DifferentTupleNullability_02() { // See https://github.com/dotnet/roslyn/issues/32006 // need to relax assertion in GetImplicitTupleLiteralConversion var source = @"using System; class Program { static T F(Func f) { return f(true); } static void G() where T : class, new() { F(b => { if (b) return (new T(), new T()); return (null, null); })/*T:(T!, T!)*/; F(b => { if (b) return (null, new T()); return (new T(), new T()); })/*T:(T!, T!)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32006: Warning inferring return type. comp.VerifyDiagnostics( // (11,59): warning CS8619: Nullability of reference types in value of type '(T?, T?)' doesn't match target type '(T, T)'. // F(b => { if (b) return (new T(), new T()); return (null, null); })/*T:(T!, T!)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, null)").WithArguments("(T?, T?)", "(T, T)").WithLocation(11, 59), // (12,32): warning CS8619: Nullability of reference types in value of type '(T?, T)' doesn't match target type '(T, T)'. // F(b => { if (b) return (null, new T()); return (new T(), new T()); })/*T:(T!, T!)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, new T())").WithArguments("(T?, T)", "(T, T)").WithLocation(12, 32)); comp.VerifyTypes(); } [WorkItem(32006, "https://github.com/dotnet/roslyn/issues/32006")] [Fact(Skip = "https://github.com/dotnet/roslyn/issues/32006")] public void LambaReturnType_DifferentTupleNullability_03() { // See https://github.com/dotnet/roslyn/issues/32006 // need to relax assertion in GetImplicitTupleLiteralConversion var source = @"using System; class Program { static T F(Func f) { return f(true); } static void G(T x, T? y) where T : class { F(b => { if (b) return (x, y); return (y, x); })/*T:(T?, T?)*/; F(b => { if (b) return (x, x); return (y, default); })/*T:(T!, T!)*/; F(b => { if (b) return (null, x); return (x, y); })/*T:(T! x, T? y)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32006: Warning inferring return type. comp.VerifyDiagnostics( // (12,47): warning CS8619: Nullability of reference types in value of type '(T? y, T?)' doesn't match target type '(T, T)'. // F(b => { if (b) return (x, x); return (y, default); })/*T:(T?, T?)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y, default)").WithArguments("(T? y, T?)", "(T, T)").WithLocation(12, 47), // (13,32): warning CS8619: Nullability of reference types in value of type '(T?, T x)' doesn't match target type '(T x, T? y)'. // F(b => { if (b) return (null, x); return (x, y); })/*T:(T?, T?)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(null, x)").WithArguments("(T?, T x)", "(T x, T? y)").WithLocation(13, 32)); comp.VerifyTypes(); } [WorkItem(32006, "https://github.com/dotnet/roslyn/issues/32006")] [Fact(Skip = "https://github.com/dotnet/roslyn/issues/32006")] public void LambaReturnType_DifferentTupleNullability_04() { // See https://github.com/dotnet/roslyn/issues/32006 // need to relax assertion in GetImplicitTupleLiteralConversion var source = @"using System; class Program { static T F(Func f) { return f(true); } static void G(T? x, object y) where T : class { F(b => { if (b) return (y, y); return (x, null); })/*T:(object!, object!)*/; F(b => { if (b) return (default, x); return (x, y); })/*T:(T? x, object! y)*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/32006: Warning inferring return type. comp.VerifyDiagnostics( // (11,47): warning CS8619: Nullability of reference types in value of type '(object? x, object?)' doesn't match target type '(object, object)'. // F(b => { if (b) return (y, y); return (x, null); })/*T:(object?, object?)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, null)").WithArguments("(object? x, object?)", "(object, object)").WithLocation(11, 47), // (12,32): warning CS8619: Nullability of reference types in value of type '(T?, object? x)' doesn't match target type '(T? x, object y)'. // F(b => { if (b) return (default, x); return (x, y); })/*T:(T?, object?)*/; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default, x)").WithArguments("(T?, object? x)", "(T? x, object y)").WithLocation(12, 32)); comp.VerifyTypes(); } [Fact] public void DisplayMultidimensionalArray() { var source = @" class C { void M(A o, A s) { o = s; } } interface A {} "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8619: Nullability of reference types in value of type 'A' doesn't match target type 'A'. // o = s; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "s").WithArguments("A", "A").WithLocation(6, 13) ); comp.VerifyTypes(); } [Fact] [WorkItem(31862, "https://github.com/dotnet/roslyn/issues/31862")] public void Issue31862_01() { var source = @" using System; using System.Collections; using System.Collections.Generic; public class Working : IEnumerable> { public IEnumerator> GetEnumerator() => null; IEnumerator IEnumerable.GetEnumerator() => throw null!; } public class Broken : IEnumerable> { IEnumerator> IEnumerable>.GetEnumerator() => null; IEnumerator IEnumerable.GetEnumerator() => throw null!; } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,58): warning CS8603: Possible null reference return. // public IEnumerator> GetEnumerator() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(8, 58), // (15,78): warning CS8603: Possible null reference return. // IEnumerator> IEnumerable>.GetEnumerator() => null; Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(15, 78) ); } [Fact] [WorkItem(31862, "https://github.com/dotnet/roslyn/issues/31862")] public void Issue31862_02() { var source = @" using System; using System.Collections; using System.Collections.Generic; public class Working : IEnumerable> { public IEnumerator?> GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } public class Broken : IEnumerable> { IEnumerator?> IEnumerable>.GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,40): warning CS8613: Nullability of reference types in return type of 'IEnumerator?> Working.GetEnumerator()' doesn't match implicitly implemented member 'IEnumerator> IEnumerable>.GetEnumerator()'. // public IEnumerator?> GetEnumerator() => throw null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "GetEnumerator").WithArguments("IEnumerator?> Working.GetEnumerator()", "IEnumerator> IEnumerable>.GetEnumerator()").WithLocation(8, 40), // (15,60): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'IEnumerator> IEnumerable>.GetEnumerator()'. // IEnumerator?> IEnumerable>.GetEnumerator() => throw null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "GetEnumerator").WithArguments("IEnumerator> IEnumerable>.GetEnumerator()").WithLocation(15, 60) ); } [Fact] [WorkItem(31862, "https://github.com/dotnet/roslyn/issues/31862")] public void Issue31862_03() { var source = @" using System; using System.Collections; using System.Collections.Generic; public class Working : IEnumerable> { public IEnumerator> GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } public class Broken : IEnumerable> { IEnumerator> IEnumerable>.GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,35): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // public IEnumerator> GetEnumerator() => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(8, 35), // (15,28): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // IEnumerator> IEnumerable>.GetEnumerator() => throw null!; Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(15, 28) ); } [Fact] [WorkItem(31862, "https://github.com/dotnet/roslyn/issues/31862")] public void Issue31862_04() { var source = @" using System; using System.Collections; using System.Collections.Generic; public class Working : IEnumerable> { public IEnumerator>? GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } public class Broken : IEnumerable> { IEnumerator>? IEnumerable>.GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(31862, "https://github.com/dotnet/roslyn/issues/31862")] public void Issue31862_05() { var source = @" using System; using System.Collections; using System.Collections.Generic; public class Working : IEnumerable> where T : class { public IEnumerator> GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } public class Broken : IEnumerable> where T : class { IEnumerator> IEnumerable>.GetEnumerator() => throw null!; IEnumerator IEnumerable.GetEnumerator() => throw null!; } "; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,40): warning CS8613: Nullability of reference types in return type of 'IEnumerator> Working.GetEnumerator()' doesn't match implicitly implemented member 'IEnumerator> IEnumerable>.GetEnumerator()'. // public IEnumerator> GetEnumerator() => throw null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "GetEnumerator").WithArguments("IEnumerator> Working.GetEnumerator()", "IEnumerator> IEnumerable>.GetEnumerator()").WithLocation(8, 40), // (15,60): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'IEnumerator> IEnumerable>.GetEnumerator()'. // IEnumerator> IEnumerable>.GetEnumerator() => throw null!; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "GetEnumerator").WithArguments("IEnumerator> IEnumerable>.GetEnumerator()").WithLocation(15, 60) ); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_UseInExpression() { var source = @" class C { void M(string? s1, string s2) { string s3 = (s1 ??= s2); string? s4 = null, s5 = null; string s6 = (s4 ??= s5); // Warn 1 s4.ToString(); // Warn 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // string s6 = (s4 ??= s5); // Warn 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "s4 ??= s5").WithLocation(8, 22), // (9,9): warning CS8602: Dereference of a possibly null reference. // s4.ToString(); // Warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s4").WithLocation(9, 9)); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_AssignsState() { var source = @" class C { object? F = null; void M(C? c1, C c2, C c3) { c1 ??= c2; c1.ToString(); if (c3.F == null) return; c1 = null; c1 ??= c3; c1.F.ToString(); // Warn 1 c1 = null; c1 ??= c3; c1.ToString(); c1.F.ToString(); // Warn 2 if (c1.F == null) return; c1 ??= c2; c1.F.ToString(); // Warn 3 // We could support this in the future if MakeSlot is made smarter to understand // that the slot of a ??= is the slot of the left-hand side. https://github.com/dotnet/roslyn/issues/32501 (c1 ??= c3).F.ToString(); // Warn 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // c1.F.ToString(); // Warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(14, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // c1.F.ToString(); // Warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(19, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. // c1.F.ToString(); // Warn 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1.F").WithLocation(23, 9), // (27,9): warning CS8602: Dereference of a possibly null reference. // (c1 ??= c3).F.ToString(); // Warn 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(c1 ??= c3).F").WithLocation(27, 9)); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_RightStateValidInRightOnly() { var source = @" class C { C GetC(C c) => c; void M(C? c1, C? c2, C c3) { c1 ??= (c2 = c3); c1.ToString(); c2.ToString(); // Warn 1 c1 = null; c2 = null; c1 ??= (c2 = c3).GetC(c2); c1.ToString(); c2.ToString(); // Warn 2 c1 = null; c2 = null; c1 ??= (c2 = c3).GetC(c1); // Warn 3 c1.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // c2.ToString(); // Warn 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(9, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // c2.ToString(); // Warn 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c2").WithLocation(15, 9), // (19,31): warning CS8604: Possible null reference argument for parameter 'c' in 'C C.GetC(C c)'. // c1 ??= (c2 = c3).GetC(c1); // Warn 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "c1").WithArguments("c", "C C.GetC(C c)").WithLocation(19, 31)); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_Contravariant() { var source = @" class C { #nullable disable C GetC() => null; #nullable enable void M(C? c1, C c2) { // nullable + non-null = non-null #nullable disable C c3 #nullable enable = (c1 ??= GetC()); _ = c1/*T:C!*/; _ = c3/*T:C!*/; // oblivious + nullable = nullable // Since c3 is non-nullable, the result is non-nullable. c1 = null; var c4 = (c3 ??= c1); _ = c3/*T:C?*/; _ = c4/*T:C?*/; // oblivious + not nullable = not nullable c3 = GetC(); var c5 = (c3 ??= c2); _ = c3/*T:C!*/; _ = c5/*T:C!*/; // not nullable + oblivious = not nullable var c6 = (c2 ??= GetC()); _ = c2/*T:C!*/; _ = c6/*T:C!*/; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_LeftNotTracked() { var source = @" class C { void M(C?[] c1, C c2) { c1[0] ??= c2; c1[0].ToString(); // Warn } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // c1[0].ToString(); // Warn Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c1[0]").WithLocation(7, 9)); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_RefReturn() { var source = @" class C { void M1(C c1, C? c2) { M2(c1) ??= c2; // Warn 1, 2 M2(c1).ToString(); M2(c2) ??= c1; M2(c2).ToString(); // Warn 3 } ref T M2(T t) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,20): warning CS8601: Possible null reference assignment. // M2(c1) ??= c2; // Warn 1, 2 Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "c2").WithLocation(6, 20), // (10,9): warning CS8602: Dereference of a possibly null reference. // M2(c2).ToString(); // Warn 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "M2(c2)").WithLocation(10, 9)); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_NestedLHS() { var source = @" class C { object? F = null; void M1(C c1, object f) { c1.F ??= f; c1.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_Conversions() { var source = @" class C { void M1(C? c1, C c2, C c3, C? c4) { c1 ??= c2; c3 ??= c4; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,16): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // c1 ??= c2; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c2").WithArguments("C", "C").WithLocation(6, 16), // (7,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // c3 ??= c4; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "c4").WithLocation(7, 16), // (7,16): warning CS8619: Nullability of reference types in value of type 'C' doesn't match target type 'C'. // c3 ??= c4; Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "c4").WithArguments("C", "C").WithLocation(7, 16)); } [WorkItem(30140, "https://github.com/dotnet/roslyn/issues/30140")] [Fact] public void NullCoalescingAssignment_LeftStillNullableOnRight() { var source = @" class C { void M1(C? c1) { c1 ??= M2(c1); c1.ToString(); } C M2(C c1) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,19): warning CS8604: Possible null reference argument for parameter 'c1' in 'C C.M2(C c1)'. // c1 ??= M2(c1); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "c1").WithArguments("c1", "C C.M2(C c1)").WithLocation(6, 19)); } [Fact] public void NullCoalescingAssignment_DefaultConvertedToNullableUnderlyingType() { var source = @" class C { void M1(int? i) { (i ??= default).ToString(); // default is converted to int, so there's no warning. } }"; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics(); } [Fact] public void Deconstruction_01() { var source = @"class Program { static void F() where U : class { (T x, U y) = default((T, U)); // 1 x.ToString(); // 2 y.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T x, U y) = default((T, U)); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default((T, U))").WithLocation(5, 22), // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(7, 9)); } [Fact] public void Deconstruction_02() { var source = @"class Program { static void F() where U : class { (T x, U y) = (default, default); // 1, 2 x.ToString(); // 3 y.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,23): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // (T x, U y) = (default, default); // 1, 2 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(5, 23), // (5,32): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T x, U y) = (default, default); // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 32), // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(7, 9)); } [Fact] public void Deconstruction_03() { var source = @"class Program { static void F() where T : class, new() { (T x, T? y) = (null, new T()); // 1 x.ToString(); // 2 y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,24): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T x, T? y) = (null, new T()); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 24), // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9)); } [Fact] public void Deconstruction_04() { var source = @"class Program { static void F(T x, T? y) where T : class { (T a, T? b) = (x, y); a.ToString(); b.ToString(); // 1 (a, b) = (y, x); // 2 a.ToString(); // 3 b.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // b.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b").WithLocation(7, 9), // (8,19): warning CS8600: Converting null literal or possible null value to non-nullable type. // (a, b) = (y, x); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "y").WithLocation(8, 19), // (9,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(9, 9)); } [Fact] public void Deconstruction_05() { var source = @"class Program { static void F((T, T?) t) where T : class { (T a, T? b) = t; a.ToString(); b.ToString(); // 1 (b, a) = t; // 2 a.ToString(); // 3 b.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // b.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b").WithLocation(7, 9), // (8,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // (b, a) = t; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(8, 18), // (9,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(9, 9)); } [Fact] public void Deconstruction_06() { var source = @"class Program { static void F() where T : class, new() { (T, T?) t = (default, new T()); // 1 (T a, T? b) = t; // 2 a.ToString(); // 3 b.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,21): warning CS8619: Nullability of reference types in value of type '(T?, T)' doesn't match target type '(T, T?)'. // (T, T?) t = (default, new T()); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default, new T())").WithArguments("(T?, T)", "(T, T?)").WithLocation(5, 21), // (6,23): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T a, T? b) = t; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(6, 23), // (7,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(7, 9)); } [Fact] public void Deconstruction_07() { var source = @"class Program { static void F() where U : class { var (x, y) = default((T, U)); x.ToString(); // 1 y.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(6, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(7, 9)); } [Fact] public void Deconstruction_08() { var source = @"class Program { static void F() where T : class, new() { T x = default; // 1 T? y = new T(); var (a, b) = (x, y); a.ToString(); // 2 b.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x = default; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(5, 15), // (8,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(8, 9)); } [Fact] public void Deconstruction_09() { var source = @"class Program { static void F() where T : class, new() { (T, T?) t = (default, new T()); // 1 var (a, b) = t; a.ToString(); // 2 b.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,21): warning CS8619: Nullability of reference types in value of type '(T?, T)' doesn't match target type '(T, T?)'. // (T, T?) t = (default, new T()); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(default, new T())").WithArguments("(T?, T)", "(T, T?)").WithLocation(5, 21), // (7,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(7, 9)); } [Fact] public void Deconstruction_10() { var source = @"class Program { static void F((T, T?) t) where T : class { if (t.Item2 == null) return; t.Item1 = null; // 1 var (a, b) = t; a.ToString(); // 2 b.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // t.Item1 = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 19), // (8,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(8, 9)); } [Fact] public void Deconstruction_11() { var source = @"class Program { static void F(object? x, object y, string? z) { ((object? a, object? b), string? c) = ((x, y), z); a.ToString(); // 1 b.ToString(); c.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9)); } [Fact] public void Deconstruction_12() { var source = @"class Program { static void F((object?, object) x, string? y) { ((object? a, object? b), string? c) = (x, y); a.ToString(); // 1 b.ToString(); c.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9)); } [Fact] public void Deconstruction_13() { var source = @"class Program { static void F(((object?, object), string?) t) { ((object? a, object? b), string? c) = t; a.ToString(); // 1 b.ToString(); c.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(8, 9)); } [Fact] public void Deconstruction_14() { var source = @"class Program { static void F(object? x, string y, (object, string?) z) { ((object?, object?) a, (object? b, object? c)) = ((x, y), z); a.Item1.ToString(); // 1 a.Item2.ToString(); b.ToString(); c.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // a.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.Item1").WithLocation(6, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(9, 9)); } [Fact] public void Deconstruction_15() { var source = @"class Program { static void F((object?, string) x, object y, string? z) { ((object a, object b), (object x, object y) c) = (x, (y, z)); // 1, 2 a.ToString(); // 3 b.ToString(); c.x.ToString(); c.y.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,59): warning CS8600: Converting null literal or possible null value to non-nullable type. // ((object a, object b), (object x, object y) c) = (x, (y, z)); // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(5, 59), // (5,62): warning CS8619: Nullability of reference types in value of type '(object y, object? z)' doesn't match target type '(object x, object y)'. // ((object a, object b), (object x, object y) c) = (x, (y, z)); // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(y, z)").WithArguments("(object y, object? z)", "(object x, object y)").WithLocation(5, 62), // (6,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(6, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // c.y.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.y").WithLocation(9, 9)); } [Fact] public void Deconstruction_16() { var source = @"class Program { static void F(T t, U? u) where U : class { T x; U y; (x, _) = (t, u); (_, y) = (t, u); // 1 (x, _, (_, y)) = (t, t, (u, u)); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,22): warning CS8600: Converting null literal or possible null value to non-nullable type. // (_, y) = (t, u); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u").WithLocation(8, 22), // (9,37): warning CS8600: Converting null literal or possible null value to non-nullable type. // (x, _, (_, y)) = (t, t, (u, u)); // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u").WithLocation(9, 37)); } [Fact] public void Deconstruction_17() { var source = @"class Pair where U : class { internal void Deconstruct(out T t, out U? u) => throw null!; } class Program { static void F() where U : class { var (t, u) = new Pair(); t.ToString(); // 1 u.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // t.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // u.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "u").WithLocation(11, 9)); } [Fact] public void Deconstruction_18() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F() where T : class { (T x1, T y1) = new Pair(); // 1 x1.ToString(); y1.ToString(); // 2 (T? x2, T? y2) = new Pair(); x2.ToString(); y2.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T x1, T y1) = new Pair(); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "T y1").WithLocation(9, 16), // (11,9): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(11, 9), // (14,9): warning CS8602: Dereference of a possibly null reference. // y2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(14, 9)); } [Fact] public void Deconstruction_19() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F() where U : class { (T, U?) t = new Pair(); t.Item1.ToString(); // 1 t.Item2.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,21): error CS0029: Cannot implicitly convert type 'Pair' to '(T, U?)' // (T, U?) t = new Pair(); Diagnostic(ErrorCode.ERR_NoImplicitConv, "new Pair()").WithArguments("Pair", "(T, U?)").WithLocation(9, 21), // (10,9): warning CS8602: Dereference of a possibly null reference. // t.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item1").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // t.Item2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(11, 9)); } [Fact] public void Deconstruction_TupleAndDeconstruct() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F(T? x, Pair y) where T : class { (T a, (T? b, T? c)) = (x, y); // 1 a.ToString(); // 2 b.ToString(); c.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,32): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T a, (T? b, T? c)) = (x, y); // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x").WithLocation(9, 32), // (10,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(12, 9)); } [Fact] [WorkItem(33005, "https://github.com/dotnet/roslyn/issues/33005")] public void Deconstruction_DeconstructAndTuple() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F(Pair p) where T : class { (T a, (T? b, T? c)) = p; // 1 a.ToString(); // 2 b.ToString(); c.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T a, (T? b, T? c)) = p; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "T a").WithLocation(9, 10), // (10,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(12, 9) ); } [Fact] [WorkItem(33005, "https://github.com/dotnet/roslyn/issues/33005")] public void Deconstruction_DeconstructAndDeconstruct() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F(Pair> p) where T : class { (T a, (T? b, T? c)) = p; // 1 a.ToString(); // 2 b.ToString(); c.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,10): warning CS8600: Converting null literal or possible null value to non-nullable type. // (T a, (T? b, T? c)) = p; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "T a").WithLocation(9, 10), // (10,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(12, 9) ); } [Fact] public void Deconstruction_20() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F1(Pair? p1) { var (x, y) = p1; // 1 (x, y) = p1; } static void F2(Pair? p2) { if (p2 == null) return; var (x, y) = p2; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,22): warning CS8602: Dereference of a possibly null reference. // var (x, y) = p1; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p1").WithLocation(9, 22)); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_21() { var source = @"class Program { static void F((T, U) t) where U : struct { object? x; object? y; var u = ((x, y) = t); u.x.ToString(); // 1 u.y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/33011: Should warn for `u.x`. comp.VerifyDiagnostics(); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_22() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F(Pair p) { object? x; object? y; var t = ((x, y) = p); t.x.ToString(); t.y.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/33011: Should warn for `t.y`. comp.VerifyDiagnostics(); } // As above, but with struct type. [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_23() { var source = @"struct Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F(Pair p) { object? x; object? y; var t = ((x, y) = p); t.x.ToString(); t.y.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); // https://github.com/dotnet/roslyn/issues/33011: Should warn for `t.y` only. comp.VerifyDiagnostics(); } [Fact] public void Deconstruction_24() { var source = @"class Program { static void F(bool b, object x, object? y) { (object?, object, object?, object, object?, (object, object?), object, object, object?, object) t = (x, x, x, y, y, (y, x), x, x, y, y); // 1 var (_1, _2, _3, _4, _5, (_6a, _6b), _7, _8, _9, _10) = t; _1.ToString(); _2.ToString(); _3.ToString(); _4.ToString(); // 2 _5.ToString(); // 3 _6a.ToString(); // 4 _6b.ToString(); _7.ToString(); _8.ToString(); _9.ToString(); // 5 _10.ToString(); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,109): warning CS8619: Nullability of reference types in value of type '(object, object, object, object?, object?, (object? y, object x), object, object, object?, object?)' doesn't match target type '(object?, object, object?, object, object?, (object, object?), object, object, object?, object)'. // (object?, object, object?, object, object?, (object, object?), object, object, object?, object) t = (x, x, x, y, y, (y, x), x, x, y, y); // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "(x, x, x, y, y, (y, x), x, x, y, y)").WithArguments("(object, object, object, object?, object?, (object? y, object x), object, object, object?, object?)", "(object?, object, object?, object, object?, (object, object?), object, object, object?, object)").WithLocation(5, 109), // (10,9): warning CS8602: Dereference of a possibly null reference. // _4.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "_4").WithLocation(10, 9), // (11,9): warning CS8602: Dereference of a possibly null reference. // _5.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "_5").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // _6a.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "_6a").WithLocation(12, 9), // (16,9): warning CS8602: Dereference of a possibly null reference. // _9.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "_9").WithLocation(16, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // _10.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "_10").WithLocation(17, 9)); } [Fact] [WorkItem(33017, "https://github.com/dotnet/roslyn/issues/33017")] public void Deconstruction_25() { var source = @"using System.Collections.Generic; class Program { static void F1(IEnumerable<(T, T)> e1) { foreach (var (x1, y1) in e1) { x1.ToString(); // 1 y1.ToString(); // 2 } foreach ((object? z1, object? w1) in e1) { z1.ToString(); // 3 w1.ToString(); // 4 } } static void F2(IEnumerable<(T, T?)> e2) where T : class { foreach (var (x2, y2) in e2) { x2.ToString(); y2.ToString(); // 5 } foreach ((object? z2, object? w2) in e2) { z2.ToString(); w2.ToString(); // 6 } } static void F3(IEnumerable<(T, T?)> e3) where T : struct { foreach (var (x3, y3) in e3) { x3.ToString(); _ = y3.Value; // 7 } foreach ((object? z3, object? w3) in e3) { z3.ToString(); w3.ToString(); // 8 } } static void F4((object?, object?)[] arr) { foreach ((object, object) el in arr) // 9 { el.Item1.ToString(); el.Item2.ToString(); } foreach ((object i1, object i2) in arr) // 10, 11 { i1.ToString(); // 12 i2.ToString(); // 13 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8602: Dereference of a possibly null reference. // x1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(8, 13), // (9,13): warning CS8602: Dereference of a possibly null reference. // y1.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(9, 13), // (13,13): warning CS8602: Dereference of a possibly null reference. // z1.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(13, 13), // (14,13): warning CS8602: Dereference of a possibly null reference. // w1.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w1").WithLocation(14, 13), // (22,13): warning CS8602: Dereference of a possibly null reference. // y2.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(22, 13), // (27,13): warning CS8602: Dereference of a possibly null reference. // w2.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w2").WithLocation(27, 13), // (35,17): warning CS8629: Nullable value type may be null. // _ = y3.Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y3").WithLocation(35, 17), // (40,13): warning CS8602: Dereference of a possibly null reference. // w3.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "w3").WithLocation(40, 13), // (45,35): warning CS8619: Nullability of reference types in value of type '(object?, object?)' doesn't match target type '(object, object)'. // foreach ((object, object) el in arr) // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "el").WithArguments("(object?, object?)", "(object, object)").WithLocation(45, 35), // (51,44): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach ((object i1, object i2) in arr) // 10, 11 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "arr").WithLocation(51, 44), // (51,44): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach ((object i1, object i2) in arr) // 10, 11 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "arr").WithLocation(51, 44), // (53,13): warning CS8602: Dereference of a possibly null reference. // i1.ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "i1").WithLocation(53, 13), // (54,13): warning CS8602: Dereference of a possibly null reference. // i2.ToString(); // 13 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "i2").WithLocation(54, 13) ); } [Fact] public void Deconstruction_26() { var source = @"class Program { static void F(bool c, object? a, object? b) { if (b == null) return; var (x, y, z, w) = c ? (a, b, a, b) : (a, a, b, b); x.ToString(); // 1 y.ToString(); // 2 z.ToString(); // 3 w.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(7, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(8, 9), // (9,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(9, 9)); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_27() { var source = @"class Program { static void F(object? x, object y) { if (x == null) return; y = null; // 1 var t = (new[] { x }, new[] { y }); var (ax, ay) = t; ax[0].ToString(); ay[0].ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // ay[0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ay[0]").WithLocation(10, 9) ); } [Fact] public void Deconstruction_28() { var source = @"class Program { public void Deconstruct(out int x, out int y) => throw null!; static void F(Program? p) { var (x, y) = p; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,22): warning CS8602: Dereference of a possibly null reference. // var (x, y) = p; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p").WithLocation(7, 22) ); } [Fact] public void Deconstruction_29() { var source = @"class Pair { internal void Deconstruct(out T t, out U u) => throw null!; } class Program { static void F(Pair?> p) { (object? x, (object y, object? z)) = p; // 1 x.ToString(); // 2 y.ToString(); z.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // (object? x, (object y, object? z)) = p; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(object? x, (object y, object? z)) = p").WithLocation(9, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(12, 9) ); } [Fact] public void Deconstruction_30() { var source = @" class Pair { public void Deconstruct(out T t, out U u) => throw null!; } class Program { static Pair CreatePair(T t, U u) => new Pair(); static void F(string? x, object? y) { if (x == null) return; var p = CreatePair(x, y); (x, y) = p; x.ToString(); // ok y.ToString(); // warning } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(17, 9) ); } [Fact] public void Deconstruction_31() { var source = @" class Pair { public void Deconstruct(out T t, out U u) => throw null!; } class Program { static Pair CreatePair(T t, U u) => new Pair(); static void F(string? x, object? y) { if (x == null) return; var p = CreatePair(x, CreatePair(x, y)); object? z; (z, (x, y)) = p; x.ToString(); // ok y.ToString(); // warning } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(18, 9) ); } [Fact] [WorkItem(35131, "https://github.com/dotnet/roslyn/issues/35131")] [WorkItem(33017, "https://github.com/dotnet/roslyn/issues/33017")] public void Deconstruction_32() { var source = @" using System.Collections.Generic; class Pair { public void Deconstruct(out T t, out U u) => throw null!; } class Program { static List> CreatePairList(T t, U u) => new List>(); static void F(string x, object? y) { foreach((var x2, var y2) in CreatePairList(x, y)) { x2.ToString(); y2.ToString(); // 1 } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (17,13): warning CS8602: Dereference of a possibly null reference. // y2.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(17, 13) ); } [Fact] [WorkItem(35131, "https://github.com/dotnet/roslyn/issues/35131")] [WorkItem(33017, "https://github.com/dotnet/roslyn/issues/33017")] public void Deconstruction_33() { var source = @" using System.Collections.Generic; class Pair { public void Deconstruct(out T t, out U u) => throw null!; } class Program { static List> CreatePairList(T t, U u) => new List>(); static void F(T x, T? y) where T : class { x = null; // 1 if (y == null) return; foreach((T x2, T? y2) in CreatePairList(x, y)) // 2 { x2.ToString(); // 3 y2.ToString(); } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(15, 13), // (17,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // foreach((T x2, T? y2) in CreatePairList(x, y)) // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "T x2").WithLocation(17, 18), // (19,13): warning CS8602: Dereference of a possibly null reference. // x2.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(19, 13) ); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_34() { var source = @"class Program { static void F(object? x, object y) { if (x == null) return; y = null; // 1 var t = (new[] { x }, y); var (ax, ay) = t; ax[0].ToString(); ay.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(6, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // ay.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ay").WithLocation(10, 9) ); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_35() { var source = @" using System.Collections.Generic; class Program { static List MakeList(T a) { throw null!; } static void F(object? x, object y) { if (x == null) return; y = null; // 1 var t = (new[] { x }, MakeList(y)); var (ax, ay) = t; ax[0].ToString(); ay[0].ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 13), // (18,9): warning CS8602: Dereference of a possibly null reference. // ay[0].ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ay[0]").WithLocation(18, 9) ); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_36() { var source = @" using System.Collections.Generic; class Program { static List MakeList(T a) where T : notnull { throw null!; } static void F(object? x, object y) { if (x == null) return; y = null; // 1 var t = (new[] { x }, MakeList(y)); // 2 var (ax, ay) = t; ax[0].ToString(); ay[0].ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 13), // (14,31): warning CS8714: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'Program.MakeList(T)'. Nullability of type argument 'object?' doesn't match 'notnull' constraint. // var t = (new[] { x }, MakeList(y)); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint, "MakeList").WithArguments("Program.MakeList(T)", "T", "object?").WithLocation(14, 31), // (17,9): warning CS8602: Dereference of a possibly null reference. // ay[0].ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ay[0]").WithLocation(17, 9) ); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_37() { var source = @" using System.Collections.Generic; class Program { static List MakeList(T a) { throw null!; } static void F(object? x, object y) { if (x == null) return; y = null; // 1 var ylist = MakeList(y); var ylist2 = MakeList(ylist); var ylist3 = MakeList(ylist2); ylist3 = null; // 2 var t = (new[] { x }, MakeList(ylist3)); var (ax, ay) = t; ax[0].ToString(); ay[0].ToString(); // 3 var ay0 = ay[0]; if (ay0 == null) return; ay0[0].ToString(); ay0[0][0].ToString(); ay0[0][0][0].ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8600: Converting null literal or possible null value to non-nullable type. // y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 13), // (17,18): warning CS8600: Converting null literal or possible null value to non-nullable type. // ylist3 = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(17, 18), // (21,9): warning CS8602: Dereference of a possibly null reference. // ay[0].ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ay[0]").WithLocation(21, 9), // (26,9): warning CS8602: Dereference of a possibly null reference. // ay0[0][0][0].ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ay0[0][0][0]").WithLocation(26, 9) ); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_38() { var source = @" class Program { static void F(object? x1, object y1) { var t = (x1, y1); var (x2, y2) = t; if (x1 == null) return; y1 = null; // 1 var u = (x1, y1); (x2, y2) = u; // 2 x2 = null; y2 = null; // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(9, 14), // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // (x2, y2) = u; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "u").WithLocation(11, 20), // (13,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y2 = null; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 14) ); } [Fact] [WorkItem(33019, "https://github.com/dotnet/roslyn/issues/33019")] public void Deconstruction_39() { var source = @" class Program { static void F(object? x1, object y1) { if (x1 == null) return; y1 = null; // 1 var t = (x1, y1); var (x2, y2) = (t.Item1, t.Item2); x2 = null; // 2 y2 = null; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // y1 = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 14), // (10,14): warning CS8600: Converting null literal or possible null value to non-nullable type. // x2 = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(10, 14) ); } [Fact] public void Deconstruction_ExtensionMethod_01() { var source = @"class Pair { } static class E { internal static void Deconstruct(this Pair? p, out object x, out object? y) => throw null!; } class Program { static void F(Pair? p) { (object? x, object? y) = p; x.ToString(); y.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(14, 9)); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_02() { var source = @"struct Pair { } static class E { internal static void Deconstruct(this Pair p, out T t, out U u) => throw null!; } class Program { static void F(Pair p) where U : class { var (x, y) = p; x.ToString(); // 1 y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 9) ); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_03() { var source = @"class Pair { } static class E { internal static void Deconstruct(this Pair p, out T t, out U u) => throw null!; } class Program { static void F(Pair? p) { (object? x, object? y) = p; // 1 x.ToString(); // 2 y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,34): warning CS8604: Possible null reference argument for parameter 'p' in 'void E.Deconstruct(Pair p, out object? t, out object u)'. // (object? x, object? y) = p; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "p").WithArguments("p", "void E.Deconstruct(Pair p, out object? t, out object u)").WithLocation(12, 34), // (13,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 9) ); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_04() { var source = @"class Pair { } static class E { internal static void Deconstruct(this Pair p, out T t, out U u) => throw null!; } class Program { static void F(Pair?> p) { (object? x, (object y, object? z)) = p; // 1 x.ToString(); // 2 y.ToString(); z.ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,9): warning CS8604: Possible null reference argument for parameter 'p' in 'void E.Deconstruct(Pair p, out object t, out object? u)'. // (object? x, (object y, object? z)) = p; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(object? x, (object y, object? z)) = p").WithArguments("p", "void E.Deconstruct(Pair p, out object t, out object? u)").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(15, 9) ); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_05() { var source = @"class Pair { } static class E { internal static void Deconstruct(this Pair? p, out T t, out U u) => throw null!; } class Program { static void F(Pair> p) { (object? x, (object y, object? z)) = p; x.ToString(); // 1 y.ToString(); z.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(15, 9) ); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_06() { var source = @"class Pair { } static class E { internal static void Deconstruct(this Pair? p, out T t, out U u) => throw null!; } class Program { static Pair CreatePair(T t, U u) => new Pair(); static void F(string? x, object? y) { if (x == null) return; var p = CreatePair(x, CreatePair(x, y)); object? z; (z, (x, y)) = p; x.ToString(); // ok y.ToString(); // warning } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(19, 9) ); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_ConstraintWarning() { var source = @"class Pair where T : class? { } static class E { internal static void Deconstruct(this Pair p, out T t, out U u) where T : class => throw null!; } class Program { static void F(Pair p) { var (x, y) = p; // 1 x.ToString(); // 2 y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,22): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'E.Deconstruct(Pair, out T, out U)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // var (x, y) = p; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "p").WithArguments("E.Deconstruct(Pair, out T, out U)", "T", "object?").WithLocation(14, 22), // (15,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(15, 9) ); } [Fact] [WorkItem(33006, "https://github.com/dotnet/roslyn/issues/33006")] public void Deconstruction_ExtensionMethod_ConstraintWarning_Nested() { var source = @"class Pair where T : class? { } class Pair2 where U : class? { } static class E { internal static void Deconstruct(this Pair p, out T t, out U u) where T : class => throw null!; internal static void Deconstruct(this Pair2 p, out T t, out U u) where U : class => throw null!; } class Program { static void F(Pair?> p) { var (x, (y, z)) = p; // 1, 2, 3 x.ToString(); // 4 y.ToString(); z.ToString(); // 5 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (21,9): warning CS8604: Possible null reference argument for parameter 'p' in 'void E.Deconstruct(Pair2 p, out object t, out object? u)'. // var (x, (y, z)) = p; // 1, 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "var (x, (y, z)) = p").WithArguments("p", "void E.Deconstruct(Pair2 p, out object t, out object? u)").WithLocation(21, 9), // (21,27): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'E.Deconstruct(Pair, out T, out U)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // var (x, (y, z)) = p; // 1, 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "p").WithArguments("E.Deconstruct(Pair, out T, out U)", "T", "object?").WithLocation(21, 27), // (21,27): warning CS8634: The type 'object?' cannot be used as type parameter 'U' in the generic type or method 'E.Deconstruct(Pair2, out T, out U)'. Nullability of type argument 'object?' doesn't match 'class' constraint. // var (x, (y, z)) = p; // 1, 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "p").WithArguments("E.Deconstruct(Pair2, out T, out U)", "U", "object?").WithLocation(21, 27), // (22,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(22, 9), // (24,9): warning CS8602: Dereference of a possibly null reference. // z.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(24, 9) ); } [Fact] public void Deconstruction_EvaluationOrder_01() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { internal object F; } class Program { static void F0(C? x0, C? y0) { (x0.F, // 1 x0.F) = (y0.F, // 2 y0.F); } static void F1(C? x1, C? y1) { (x1.F, // 3 _) = (y1.F, // 4 x1.F); } static void F2(C? x2, C? y2) { (_, y2.F) = // 5 (y2.F, x2.F); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,10): warning CS8602: Dereference of a possibly null reference. // (x0.F, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(11, 10), // (13,18): warning CS8602: Dereference of a possibly null reference. // (y0.F, // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(13, 18), // (18,10): warning CS8602: Dereference of a possibly null reference. // (x1.F, // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(18, 10), // (20,18): warning CS8602: Dereference of a possibly null reference. // (y1.F, // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(20, 18), // (26,13): warning CS8602: Dereference of a possibly null reference. // y2.F) = // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(26, 13), // (28,21): warning CS8602: Dereference of a possibly null reference. // x2.F); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(28, 21)); } [Fact] public void Deconstruction_EvaluationOrder_02() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class C { internal object F; } class Program { static void F0(C? x0, C? y0, C? z0) { ((x0.F, // 1 y0.F), // 2 z0.F) = // 3 ((y0.F, z0.F), x0.F); } static void F1(C? x1, C? y1, C? z1) { ((x1.F, // 4 _), x1.F) = ((y1.F, // 5 z1.F), // 6 z1.F); } static void F2(C? x2, C? y2, C? z2) { ((_, _), x2.F) = // 7 ((x2.F, y2.F), // 8 z2.F); // 9 } static void F3(C? x3, C? y3, C? z3) { (x3.F, // 10 (x3.F, y3.F)) = // 11 (y3.F, (z3.F, // 12 x3.F)); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,11): warning CS8602: Dereference of a possibly null reference. // ((x0.F, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(11, 11), // (12,13): warning CS8602: Dereference of a possibly null reference. // y0.F), // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(12, 13), // (13,17): warning CS8602: Dereference of a possibly null reference. // z0.F) = // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(13, 17), // (20,11): warning CS8602: Dereference of a possibly null reference. // ((x1.F, // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(20, 11), // (23,23): warning CS8602: Dereference of a possibly null reference. // ((y1.F, // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(23, 23), // (24,25): warning CS8602: Dereference of a possibly null reference. // z1.F), // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z1").WithLocation(24, 25), // (31,17): warning CS8602: Dereference of a possibly null reference. // x2.F) = // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(31, 17), // (33,25): warning CS8602: Dereference of a possibly null reference. // y2.F), // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(33, 25), // (34,29): warning CS8602: Dereference of a possibly null reference. // z2.F); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z2").WithLocation(34, 29), // (38,10): warning CS8602: Dereference of a possibly null reference. // (x3.F, // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(38, 10), // (40,17): warning CS8602: Dereference of a possibly null reference. // y3.F)) = // 11 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y3").WithLocation(40, 17), // (42,26): warning CS8602: Dereference of a possibly null reference. // (z3.F, // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z3").WithLocation(42, 26)); } [Fact] public void Deconstruction_EvaluationOrder_03() { var source = @"#pragma warning disable 8618 class Pair { internal void Deconstruct(out T t, out U u) => throw null!; internal T First; internal U Second; } class Program { static void F0(Pair? p0) { (_, _) = p0; // 1 } static void F1(Pair? p1) { (_, p1.Second) = // 2 p1; } static void F2(Pair? p2) { (p2.First, // 3 _) = p2; } static void F3(Pair? p3) { (p3.First, // 4 p3.Second) = p3; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,17): warning CS8602: Dereference of a possibly null reference. // p0; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p0").WithLocation(14, 17), // (19,13): warning CS8602: Dereference of a possibly null reference. // p1.Second) = // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p1").WithLocation(19, 13), // (24,10): warning CS8602: Dereference of a possibly null reference. // (p2.First, // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p2").WithLocation(24, 10), // (30,10): warning CS8602: Dereference of a possibly null reference. // (p3.First, // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "p3").WithLocation(30, 10)); } [Fact] public void Deconstruction_EvaluationOrder_04() { var source = @"#pragma warning disable 0649 #pragma warning disable 8618 class Pair { internal void Deconstruct(out object x, out object y) => throw null!; internal object First; internal object Second; } class Program { static void F0(Pair? x0, Pair? y0) { ((x0.First, // 1 _), y0.First) = // 2 (x0, y0.Second); } static void F1(Pair? x1, Pair? y1) { ((_, y1.First), // 3 _) = (x1, // 4 y1.Second); } static void F2(Pair? x2, Pair? y2) { ((_, _), x2.First) = // 5 (x2, y2.Second); // 6 } static void F3(Pair? x3, Pair? y3) { (x3.First, // 7 (_, y3.First)) = // 8 (y3.Second, x3); } static void F4(Pair? x4, Pair? y4) { (_, (x4.First, // 9 _)) = (x4.Second, y4); // 10 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,11): warning CS8602: Dereference of a possibly null reference. // ((x0.First, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(13, 11), // (15,17): warning CS8602: Dereference of a possibly null reference. // y0.First) = // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(15, 17), // (22,13): warning CS8602: Dereference of a possibly null reference. // y1.First), // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1").WithLocation(22, 13), // (24,22): warning CS8602: Dereference of a possibly null reference. // (x1, // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(24, 22), // (31,17): warning CS8602: Dereference of a possibly null reference. // x2.First) = // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(31, 17), // (33,25): warning CS8602: Dereference of a possibly null reference. // y2.Second); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2").WithLocation(33, 25), // (37,10): warning CS8602: Dereference of a possibly null reference. // (x3.First, // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(37, 10), // (39,17): warning CS8602: Dereference of a possibly null reference. // y3.First)) = // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y3").WithLocation(39, 17), // (46,14): warning CS8602: Dereference of a possibly null reference. // (x4.First, // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x4").WithLocation(46, 14), // (49,25): warning CS8602: Dereference of a possibly null reference. // y4); // 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y4").WithLocation(49, 25)); } [Fact] public void Deconstruction_ImplicitBoxingConversion_01() { var source = @"class Program { static void F((T, U, V?) t) where U : struct where V : struct { (object a, object b, object c) = t; // 1, 2 a.ToString(); // 3 b.ToString(); c.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,42): warning CS8600: Converting null literal or possible null value to non-nullable type. // (object a, object b, object c) = t; // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(7, 42), // (7,42): warning CS8600: Converting null literal or possible null value to non-nullable type. // (object a, object b, object c) = t; // 1, 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t").WithLocation(7, 42), // (8,9): warning CS8602: Dereference of a possibly null reference. // a.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // c.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(10, 9)); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_ImplicitBoxingConversion_02() { var source = @"class Program { static void F(T x, T? y) where T : struct { (T?, T?) t = (x, y); (object? a, object? b) = t; a.ToString(); b.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // b.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b").WithLocation(8, 9)); } [Fact] public void Deconstruction_ImplicitNullableConversion_01() { var source = @"struct S { internal object F; } class Program { static void F(S s) { (S? x, S? y, S? z) = (s, new S(), default); _ = x.Value; x.Value.F.ToString(); _ = y.Value; y.Value.F.ToString(); // 1 _ = z.Value; // 2 z.Value.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (3,21): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value null // internal object F; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "null").WithLocation(3, 21), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.Value.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.F").WithLocation(13, 9), // (14,13): warning CS8629: Nullable value type may be null. // _ = z.Value; // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "z").WithLocation(14, 13)); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_ImplicitNullableConversion_02() { var source = @"#pragma warning disable 0649 struct S { internal object F; } class Program { static void F(S s) { (S, S) t = (s, new S()); (S? x, S? y) = t; _ = x.Value; x.Value.F.ToString(); _ = y.Value; y.Value.F.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // y.Value.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Value.F").WithLocation(15, 9)); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_ImplicitNullableConversion_03() { var source = @"#pragma warning disable 0649 struct S { internal T F; } class Program { static void F((S, S) t) where T : class, new() { (S? x, S? y) = t; // 1, 2 x.Value.F.ToString(); // 3 y.Value.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,31): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S?'. // (S? x, S? y) = t; // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("S", "S?").WithLocation(10, 31), // (10,31): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S?'. // (S? x, S? y) = t; // 1, 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("S", "S?").WithLocation(10, 31), // (11,9): warning CS8602: Dereference of a possibly null reference. // x.Value.F.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Value.F").WithLocation(11, 9)); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_ImplicitNullableConversion_04() { var source = @"#pragma warning disable 0649 struct S { internal T F; } class Program { static void F((object, (S, S)) t) where T : class, new() { (object a, (S? x, S? y) b) = t; // 1 b.x.Value.F.ToString(); // 2 b.y.Value.F.ToString(); // 3, 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,45): warning CS8619: Nullability of reference types in value of type '(S, S)' doesn't match target type '(S? x, S? y)'. // (object a, (S? x, S? y) b) = t; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "t").WithArguments("(S, S)", "(S? x, S? y)").WithLocation(10, 45), // (11,9): warning CS8629: Nullable value type may be null. // b.x.Value.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b.x").WithLocation(11, 9), // (12,9): warning CS8629: Nullable value type may be null. // b.y.Value.F.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "b.y").WithLocation(12, 9), // (12,9): warning CS8602: Possible dereference of a null reference. // b.y.Value.F.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.y.Value.F").WithLocation(12, 9)); } [Fact] [WorkItem(33011, "https://github.com/dotnet/roslyn/issues/33011")] public void Deconstruction_ImplicitUserDefinedConversion_01() { var source = @"class A { } class B { public static implicit operator B?(A a) => new B(); } class Program { static void F((object, (A?, A)) t) { (object x, (B?, B) y) = t; } }"; // https://github.com/dotnet/roslyn/issues/33011 Should have warnings about conversions from B? to B and from A? to A var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] public void Deconstruction_TooFewVariables() { var source = @"class Program { static void F(object x, object y, object? z) { (object? a, object? b) = (x, y, z = 3); a.ToString(); b.ToString(); z.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS8132: Cannot deconstruct a tuple of '3' elements into '2' variables. // (object? a, object? b) = (x, y, z = 3); Diagnostic(ErrorCode.ERR_DeconstructWrongCardinality, "(object? a, object? b) = (x, y, z = 3)").WithArguments("3", "2").WithLocation(5, 9)); } [Fact] public void Deconstruction_TooManyVariables() { var source = @"class Program { static void F(object x, object y) { (object? a, object? b, object? c) = (x, y = null); a.ToString(); b.ToString(); c.ToString(); y.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS8132: Cannot deconstruct a tuple of '2' elements into '3' variables. // (object? a, object? b, object? c) = (x, y = null); Diagnostic(ErrorCode.ERR_DeconstructWrongCardinality, "(object? a, object? b, object? c) = (x, y = null)").WithArguments("2", "3").WithLocation(5, 9), // (5,53): warning CS8600: Converting null literal or possible null value to non-nullable type. // (object? a, object? b, object? c) = (x, y = null); Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(5, 53), // (9,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(9, 9)); } [Fact] public void Deconstruction_NoDeconstruct_01() { var source = @"class C { C(object o) { } static void F() { object? z = null; var (x, y) = new C(z = 1); x.ToString(); y.ToString(); z.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,14): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'. // var (x, y) = new C(z = 1); Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(7, 14), // (7,17): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'. // var (x, y) = new C(z = 1); Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(7, 17), // (7,22): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // var (x, y) = new C(z = 1); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C(z = 1)").WithArguments("C", "Deconstruct").WithLocation(7, 22), // (7,22): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C', with 2 out parameters and a void return type. // var (x, y) = new C(z = 1); Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C(z = 1)").WithArguments("C", "2").WithLocation(7, 22)); } [Fact] public void Deconstruction_NoDeconstruct_02() { var source = @"class C { C(object o) { } static void F() { object? z = null; (object? x, object? y) = new C(z = 1); x.ToString(); y.ToString(); z.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,34): error CS1061: 'C' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // (object? x, object? y) = new C(z = 1); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C(z = 1)").WithArguments("C", "Deconstruct").WithLocation(7, 34), // (7,34): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C', with 2 out parameters and a void return type. // (object? x, object? y) = new C(z = 1); Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C(z = 1)").WithArguments("C", "2").WithLocation(7, 34)); } [Fact] public void Deconstruction_TooFewDeconstructArguments() { var source = @"class C { internal void Deconstruct(out object x, out object y, out object z) => throw null!; } class Program { static void F() { (object? x, object? y) = new C(); x.ToString(); y.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,34): error CS7036: There is no argument given that corresponds to the required formal parameter 'z' of 'C.Deconstruct(out object, out object, out object)' // (object? x, object? y) = new C(); Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "new C()").WithArguments("z", "C.Deconstruct(out object, out object, out object)").WithLocation(9, 34), // (9,34): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C', with 2 out parameters and a void return type. // (object? x, object? y) = new C(); Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "2").WithLocation(9, 34)); } [Fact] public void Deconstruction_TooManyDeconstructArguments() { var source = @"class C { internal void Deconstruct(out object x, out object y) => throw null!; } class Program { static void F() { (object? x, object? y, object? z) = new C(); x.ToString(); y.ToString(); z.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,45): error CS1501: No overload for method 'Deconstruct' takes 3 arguments // (object? x, object? y, object? z) = new C(); Diagnostic(ErrorCode.ERR_BadArgCount, "new C()").WithArguments("Deconstruct", "3").WithLocation(9, 45), // (9,45): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'C', with 3 out parameters and a void return type. // (object? x, object? y, object? z) = new C(); Diagnostic(ErrorCode.ERR_MissingDeconstruct, "new C()").WithArguments("C", "3").WithLocation(9, 45)); } [Fact] [WorkItem(26628, "https://github.com/dotnet/roslyn/issues/26628")] public void ImplicitConstructor_01() { var source = @"#pragma warning disable 414 class Program { object F = null; // warning }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,16): warning CS8625: Cannot convert null literal to non-nullable reference type. // object F = null; // warning Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 16)); } [Fact] [WorkItem(26628, "https://github.com/dotnet/roslyn/issues/26628")] public void ImplicitStaticConstructor_01() { var source = @"#pragma warning disable 414 class Program { static object F = null; // warning }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,23): warning CS8625: Cannot convert null literal to non-nullable reference type. // static object F = null; // warning Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 23)); } [Fact] [WorkItem(26628, "https://github.com/dotnet/roslyn/issues/26628")] [WorkItem(33394, "https://github.com/dotnet/roslyn/issues/33394")] public void ImplicitStaticConstructor_02() { var source = @"class C { C(string s) { } static C Empty = new C(null); // warning }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (4,28): warning CS8625: Cannot convert null literal to non-nullable reference type. // static C Empty = new C(null); // warning Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(4, 28)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_01() { var source = @"class Program { static void F(ref object? x, ref object y) { x = 1; y = null; // 1 x.ToString(); y.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // y = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 13), // (8,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(8, 9)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_02() { var source = @"class Program { static void F(object? px, object py) { ref object? x = ref px; ref object y = ref py; x = 1; y = null; // 1 x.ToString(); y.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8625: Cannot convert null literal to non-nullable reference type. // y = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 13), // (10,9): warning CS8602: Dereference of a possibly null reference. // y.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(10, 9)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_03() { var source = @"class Program { static void F(ref int? x, ref int? y) { x = 1; y = null; _ = x.Value; _ = y.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(8, 13)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_04() { var source = @"class Program { static void F(int? px, int? py) { ref int? x = ref px; ref int? y = ref py; x = 1; y = null; _ = x.Value; _ = y.Value; // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,13): warning CS8629: Nullable value type may be null. // _ = y.Value; // 1 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(10, 13)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_05() { var source = @"#pragma warning disable 8618 class C { internal object F; } class Program { static void F(ref C x, ref C y) { x = new C() { F = 1 }; y = new C() { F = null }; // 1 x.F.ToString(); y.F.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,27): warning CS8625: Cannot convert null literal to non-nullable reference type. // y = new C() { F = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(11, 27), // (13,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(13, 9)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_06() { var source = @"#pragma warning disable 8618 class C { internal object? F; } class Program { static void F(ref C x, ref C y) { x = new C() { F = 1 }; y = new C() { F = null }; x.F.ToString(); y.F.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(13, 9)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_07() { var source = @"#pragma warning disable 8618 class C { internal object F; } class Program { static void F(C px, C py) { ref C x = ref px; ref C y = ref py; x = new C() { F = 1 }; y = new C() { F = null }; // 1 x.F.ToString(); y.F.ToString(); // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,27): warning CS8625: Cannot convert null literal to non-nullable reference type. // y = new C() { F = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 27), // (15,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(15, 9)); } [Fact] [WorkItem(25868, "https://github.com/dotnet/roslyn/issues/25868")] public void ByRefTarget_08() { var source = @"#pragma warning disable 8618 class C { internal object? F; } class Program { static void F(C px, C py) { ref C x = ref px; ref C y = ref py; x = new C() { F = 1 }; y = new C() { F = null }; x.F.ToString(); y.F.ToString(); // 1 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // y.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.F").WithLocation(15, 9)); } [Fact] [WorkItem(33095, "https://github.com/dotnet/roslyn/issues/33095")] public void ByRefTarget_09() { var source = @"class Program { static void F(ref string x) { ref string? y = ref x; // 1 y = null; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,29): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // ref string? y = ref x; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("string", "string?").WithLocation(5, 29) ); } [Fact] [WorkItem(33095, "https://github.com/dotnet/roslyn/issues/33095")] public void ByRefTarget_10() { var source = @"class Program { static ref string F1(ref string? x) { return ref x; // 1 } static ref string? F2(ref string y) { return ref y; // 2 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,20): warning CS8619: Nullability of reference types in value of type 'string?' doesn't match target type 'string'. // return ref x; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x").WithArguments("string?", "string").WithLocation(5, 20), // (9,20): warning CS8619: Nullability of reference types in value of type 'string' doesn't match target type 'string?'. // return ref y; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("string", "string?").WithLocation(9, 20) ); } [Fact] public void AssignmentToSameVariable_01() { var source = @"#pragma warning disable 8618 class C { internal C F; } class Program { static void F() { C a = new C() { F = null }; // 1 a = a; a.F.ToString(); // 2 C b = new C() { F = new C() { F = null } }; // 3 b.F = b.F; b.F.F.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,29): warning CS8625: Cannot convert null literal to non-nullable reference type. // C a = new C() { F = null }; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(10, 29), // (11,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // a = a; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "a = a").WithLocation(11, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // a.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a.F").WithLocation(12, 9), // (13,43): warning CS8625: Cannot convert null literal to non-nullable reference type. // C b = new C() { F = new C() { F = null } }; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(13, 43), // (14,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // b.F = b.F; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "b.F = b.F").WithLocation(14, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // b.F.F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.F.F").WithLocation(15, 9)); } [Fact] public void AssignmentToSameVariable_02() { var source = @"#pragma warning disable 8618 struct A { internal int? F; } struct B { internal A A; } class Program { static void F() { A a = new A() { F = 1 }; a = a; _ = a.F.Value; B b = new B() { A = new A() { F = 2 } }; b.A = b.A; _ = b.A.F.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // a = a; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "a = a").WithLocation(15, 9), // (18,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // b.A = b.A; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "b.A = b.A").WithLocation(18, 9)); } [Fact] public void AssignmentToSameVariable_03() { var source = @"#pragma warning disable 8618 class C { internal object F; } class Program { static void F(C? c) { c.F = c.F; // 1 c.F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // c.F = c.F; // 1 Diagnostic(ErrorCode.WRN_AssignmentToSelf, "c.F = c.F").WithLocation(10, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // c.F = c.F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(10, 9)); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_01() { var source = @"class Program { static readonly string? F = null; static readonly int? G = null; static void Main() { if (F != null) F.ToString(); if (G != null) _ = G.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_02() { var source = @"#pragma warning disable 0649 class C { static T F; static void M() { if (F == null) return; F.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_03() { var source = @"#pragma warning disable 0649 class C { internal static T F; } class Program { static void F1() { C.F.ToString(); // 1 C.F.ToString(); } static void F2() where T2 : class { C.F.ToString(); // 2 C.F.ToString(); } static void F3() where T3 : class { C.F.ToString(); C.F.ToString(); } static void F4() where T4 : struct { _ = C.F.Value; // 3 _ = C.F.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // C.F.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(10, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // C.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(15, 9), // (25,13): warning CS8629: Nullable value type may be null. // _ = C.F.Value; // 3 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "C.F").WithLocation(25, 13)); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_04() { var source = @"#pragma warning disable 0649 class C { internal static T F; } class Program { static void F1() { C.F = default; // 1 C.F.ToString(); // 2 } static void F2() where T2 : class, new() { C.F = new T2(); C.F.ToString(); } static void F3() where T3 : class, new() { C.F = new T3(); C.F.ToString(); } static void F4() where T4 : class { C.F = null; // 3 C.F.ToString(); // 4 } static void F5() where T5 : struct { C.F = default(T5); _ = C.F.Value; } static void F6() where T6 : new() { C.F = new T6(); C.F.ToString(); } static void F7() { C.F = null; // 5 _ = C.F.Length; // 6 } static void F8() { C.F = 3; _ = C.F.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // C.F = default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(10, 19), // (11,9): warning CS8602: Dereference of a possibly null reference. // C.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(11, 9), // (25,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // C.F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(25, 19), // (26,9): warning CS8602: Dereference of a possibly null reference. // C.F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(26, 9), // (40,23): warning CS8625: Cannot convert null literal to non-nullable reference type. // C.F = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(40, 23), // (41,13): warning CS8602: Dereference of a possibly null reference. // _ = C.F.Length; // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.F").WithLocation(41, 13)); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_05() { var source = @"class C { internal static T P { get => throw null!; set { } } } class Program { static void F1() { C.P = default; // 1 C.P.ToString(); // 2 } static void F2() where T2 : class, new() { C.P = new T2(); C.P.ToString(); } static void F3() where T3 : class, new() { C.P = new T3(); C.P.ToString(); } static void F4() where T4 : class { C.P = null; // 3 C.P.ToString(); // 4 } static void F5() where T5 : struct { C.P = default(T5); _ = C.P.Value; } static void F6() where T6 : new() { C.P = new T6(); C.P.ToString(); } static void F7() { C.P = null; // 5 _ = C.P.Length; // 6 } static void F8() { C.P = 3; _ = C.P.Value; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // C.P = default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(13, 19), // (14,9): warning CS8602: Dereference of a possibly null reference. // C.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.P").WithLocation(14, 9), // (28,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // C.P = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(28, 19), // (29,9): warning CS8602: Dereference of a possibly null reference. // C.P.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.P").WithLocation(29, 9), // (43,23): warning CS8625: Cannot convert null literal to non-nullable reference type. // C.P = null; // 5 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(43, 23), // (44,13): warning CS8602: Dereference of a possibly null reference. // _ = C.P.Length; // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "C.P").WithLocation(44, 13)); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_06() { var source = @"#pragma warning disable 0649 struct S { internal static T F; } class Program { static void F1() { S.F = default; // 1 S.F.ToString(); // 2 } static void F2() where T2 : class, new() { S.F = new T2(); S.F.ToString(); } static void F3() where T3 : class { S.F = null; // 3 S.F.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // S.F = default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(10, 19), // (11,9): warning CS8602: Dereference of a possibly null reference. // S.F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.F").WithLocation(11, 9), // (20,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // S.F = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(20, 19), // (21,9): warning CS8602: Dereference of a possibly null reference. // S.F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.F").WithLocation(21, 9)); } [Fact] [WorkItem(26651, "https://github.com/dotnet/roslyn/issues/26651")] public void StaticMember_07() { var source = @"struct S { internal static T P { get; set; } } class Program { static void F1() { S.P = default; // 1 S.P.ToString(); // 2 } static void F2() where T2 : class, new() { S.P = new T2(); S.P.ToString(); } static void F3() where T3 : class { S.P = null; // 3 S.P.ToString(); // 4 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,19): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type. // S.P = default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T1").WithLocation(9, 19), // (10,9): warning CS8602: Dereference of a possibly null reference. // S.P.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.P").WithLocation(10, 9), // (19,19): warning CS8625: Cannot convert null literal to non-nullable reference type. // S.P = null; // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(19, 19), // (20,9): warning CS8602: Dereference of a possibly null reference. // S.P.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "S.P").WithLocation(20, 9)); } [Fact] public void Expression_VoidReturn() { var source = @"class Program { static object F(object x) => x; static void G(object? y) { return F(y); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,9): error CS0127: Since 'Program.G(object?)' returns void, a return keyword must not be followed by an object expression // return F(y); Diagnostic(ErrorCode.ERR_RetNoObjectRequired, "return").WithArguments("Program.G(object?)").WithLocation(6, 9), // (6,18): warning CS8604: Possible null reference argument for parameter 'x' in 'object Program.F(object x)'. // return F(y); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "object Program.F(object x)").WithLocation(6, 18)); } [Fact] public void Expression_AsyncTaskReturn() { var source = @"using System.Threading.Tasks; class Program { static object F(object x) => x; static async Task G(object? y) { await Task.Delay(0); return F(y); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): error CS1997: Since 'Program.G(object?)' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'? // return F(y); Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("Program.G(object?)").WithLocation(8, 9), // (8,18): warning CS8604: Possible null reference argument for parameter 'x' in 'object Program.F(object x)'. // return F(y); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "object Program.F(object x)").WithLocation(8, 18)); } [Fact] [WorkItem(33481, "https://github.com/dotnet/roslyn/issues/33481")] public void TypelessTuple_VoidReturn() { var source = @"class Program { static void F() { return (null, string.Empty); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,9): error CS0127: Since 'Program.F()' returns void, a return keyword must not be followed by an object expression // return (null, string.Empty); Diagnostic(ErrorCode.ERR_RetNoObjectRequired, "return").WithArguments("Program.F()").WithLocation(5, 9)); } [Fact] [WorkItem(33481, "https://github.com/dotnet/roslyn/issues/33481")] public void TypelessTuple_AsyncTaskReturn() { var source = @"using System.Threading.Tasks; class Program { static async Task F() { await Task.Delay(0); return (null, string.Empty); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,9): error CS1997: Since 'Program.F()' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'? // return (null, string.Empty); Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("Program.F()").WithLocation(7, 9)); } [Fact] public void TypelessTuple_VoidLambdaReturn() { var source = @"class Program { static void F() { _ = new System.Action(() => { return (null, string.Empty); }); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): error CS8030: Anonymous function converted to a void returning delegate cannot return a value // return (null, string.Empty); Diagnostic(ErrorCode.ERR_RetNoObjectRequiredLambda, "return").WithLocation(7, 13)); } [Fact] public void TypelessTuple_AsyncTaskLambdaReturn() { var source = @"using System.Threading.Tasks; class Program { static void F() { _ = new System.Func(async () => { await Task.Delay(0); return (null, string.Empty); }); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,13): error CS8031: Async lambda expression converted to a 'Task' returning delegate cannot return a value. Did you intend to return 'Task'? // return (null, string.Empty); Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithLocation(9, 13)); } [Fact] [WorkItem(29967, "https://github.com/dotnet/roslyn/issues/29967")] public void InterfaceProperties_01() { var source = @"interface IA { T A { get; } } interface IB : IA { T B { get; } } class Program { static IB CreateB(T t) { throw null!; } static void F1(T x1) { if (x1 == null) return; var y1 = CreateB(x1); y1.A.ToString(); // 1 y1.B.ToString(); // 2 } static void F2() where T : class { T x2 = null; // 3 var y2 = CreateB(x2); y2.ToString(); y2.A.ToString(); // 4 y2.B.ToString(); // 5 } static void F3() where T : class, new() { T? x3 = new T(); var y3 = CreateB(x3); y3.A.ToString(); y3.B.ToString(); } static void F4() where T : struct { T? x4 = null; var y4 = CreateB(x4); _ = y4.A.Value; // 6 _ = y4.B.Value; // 7 } static void F5() where T : struct { T? x5 = new T(); var y5 = CreateB(x5); _ = y5.A.Value; // 8 _ = y5.B.Value; // 9 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (19,9): warning CS8602: Dereference of a possibly null reference. // y1.A.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1.A").WithLocation(19, 9), // (20,9): warning CS8602: Dereference of a possibly null reference. // y1.B.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y1.B").WithLocation(20, 9), // (24,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x2 = null; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(24, 16), // (27,9): warning CS8602: Dereference of a possibly null reference. // y2.A.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2.A").WithLocation(27, 9), // (28,9): warning CS8602: Dereference of a possibly null reference. // y2.B.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y2.B").WithLocation(28, 9), // (41,13): warning CS8629: Nullable value type may be null. // _ = y4.A.Value; // 6 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y4.A").WithLocation(41, 13), // (42,13): warning CS8629: Nullable value type may be null. // _ = y4.B.Value; // 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y4.B").WithLocation(42, 13), // (48,13): warning CS8629: Nullable value type may be null. // _ = y5.A.Value; // 8 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y5.A").WithLocation(48, 13), // (49,13): warning CS8629: Nullable value type may be null. // _ = y5.B.Value; // 9 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y5.B").WithLocation(49, 13)); } [Fact] [WorkItem(29967, "https://github.com/dotnet/roslyn/issues/29967")] public void InterfaceProperties_02() { var source = @"interface IA { T A { get; } } interface IB { T B { get; } } interface IC : IA, IB { } class Program { static IC CreateC(T t, U u) { throw null!; } static void F() where T : class, new() where U : class { T? x = new T(); T y = null; // 1 var xy = CreateC(x, y); xy.A.ToString(); xy.B.ToString(); // 2 var yx = CreateC(y, x); yx.A.ToString(); // 3 yx.B.ToString(); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(23, 15), // (26,9): warning CS8602: Dereference of a possibly null reference. // xy.B.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "xy.B").WithLocation(26, 9), // (28,9): warning CS8602: Dereference of a possibly null reference. // yx.A.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "yx.A").WithLocation(28, 9)); } [Fact] [WorkItem(29967, "https://github.com/dotnet/roslyn/issues/29967")] public void InterfaceMethods_01() { var source = @"interface IA { void A(T t); } interface IB : IA { void B(T t); } class Program { static IB CreateB(T t) { throw null!; } static void F1(T x1) { if (x1 == null) return; T y1 = default; // 1 var ix1 = CreateB(x1); var iy1 = CreateB(y1); ix1.A(y1); ix1.B(y1); iy1.A(x1); iy1.B(x1); } static void F2() where T : class, new() { T x2 = null; // 2 T? y2 = new T(); var ix2 = CreateB(x2); var iy2 = CreateB(y2); ix2.A(y2); ix2.B(y2); iy2.A(x2); // 3 iy2.B(x2); // 4 } static void F3() where T : struct { T? x3 = null; T? y3 = new T(); var ix3 = CreateB(x3); var iy3 = CreateB(y3); ix3.A(y3); ix3.B(y3); iy3.A(x3); iy3.B(x3); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,16): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // T y1 = default; // 1 Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default").WithArguments("T").WithLocation(18, 16), // (28,16): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x2 = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(28, 16), // (34,15): warning CS8604: Possible null reference argument for parameter 't' in 'void IA.A(T t)'. // iy2.A(x2); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("t", "void IA.A(T t)").WithLocation(34, 15), // (35,15): warning CS8604: Possible null reference argument for parameter 't' in 'void IB.B(T t)'. // iy2.B(x2); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("t", "void IB.B(T t)").WithLocation(35, 15)); } [Fact] [WorkItem(29967, "https://github.com/dotnet/roslyn/issues/29967")] public void InterfaceMethods_02() { var source = @"interface IA { T A(T u); } interface IB { T B(U u); } interface IC : IA, IB { } class Program { static IC CreateC(T t) { throw null!; } static void F() where T : class, new() where U : class { T? x = new T(); U y = null; // 1 var ix = CreateC(x); var iy = CreateC(y); ix.A(y).ToString(); // 2 ix.B(y).ToString(); iy.A(x).ToString(); iy.B(x).ToString(); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (23,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // U y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(23, 15), // (26,9): warning CS8602: Dereference of a possibly null reference. // ix.A(y).ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "ix.A(y)").WithLocation(26, 9), // (29,9): warning CS8602: Dereference of a possibly null reference. // iy.B(x).ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "iy.B(x)").WithLocation(29, 9)); } [Fact] [WorkItem(36018, "https://github.com/dotnet/roslyn/issues/36018")] public void InterfaceMethods_03() { var source = @" #nullable enable interface IEquatable { bool Equals(T other); } interface I1 : IEquatable, IEquatable { } class C1 : I1 { public bool Equals(string? other) { return true; } public bool Equals(I1? other) { return true; } } class C2 { void M(I1 x, string y) { x.Equals(y); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact] [WorkItem(36018, "https://github.com/dotnet/roslyn/issues/36018")] public void InterfaceMethods_04() { var source = @" #nullable enable interface IEquatable { bool Equals(T other); } interface I1 : IEquatable, IEquatable { } class C1 : I1 { public bool Equals(string other) { return true; } public bool Equals(I1 other) { return true; } } class C2 { void M(I1 x, string? y) { x.Equals(y); } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (28,18): warning CS8604: Possible null reference argument for parameter 'other' in 'bool IEquatable.Equals(string other)'. // x.Equals(y); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("other", "bool IEquatable.Equals(string other)").WithLocation(28, 18) ); } [Fact] [WorkItem(36018, "https://github.com/dotnet/roslyn/issues/36018")] public void InterfaceMethods_05() { var source = @" #nullable enable interface IEquatable { bool Equals(T other); } interface I1 : IEquatable>, IEquatable { } class C2 { void M(string? y, string z) { GetI1(y).Equals(y); GetI1(z).Equals(y); } I1 GetI1(T x) => throw null!; } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (16,25): warning CS8604: Possible null reference argument for parameter 'other' in 'bool IEquatable.Equals(string other)'. // GetI1(z).Equals(y); Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("other", "bool IEquatable.Equals(string other)").WithLocation(16, 25) ); } [Fact, WorkItem(33347, "https://github.com/dotnet/roslyn/issues/33347")] public void NestedNullConditionalAccess() { var source = @" class Node { public Node? Next = null; void M(Node node) { } private static void Test(Node? node) { node?.Next?.Next?.M(node.Next); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31909, "https://github.com/dotnet/roslyn/issues/31909")] public void NestedNullConditionalAccess2() { var source = @" public class C { public C? f; void Test1(C? c) => c?.f.M(c.f.ToString()); // nested use of `c.f` is safe void Test2(C? c) => c.f.M(c.f.ToString()); void M(string s) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,27): warning CS8602: Dereference of a possibly null reference. // void Test1(C? c) => c?.f.M(c.f.ToString()); // nested use of `c.f` is safe Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".f").WithLocation(5, 27), // (6,25): warning CS8602: Dereference of a possibly null reference. // void Test2(C? c) => c.f.M(c.f.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(6, 25), // (6,25): warning CS8602: Dereference of a possibly null reference. // void Test2(C? c) => c.f.M(c.f.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.f").WithLocation(6, 25) ); } [Fact, WorkItem(33347, "https://github.com/dotnet/roslyn/issues/33347")] public void NestedNullConditionalAccess3() { var source = @" class Node { public Node? Next = null; static Node M2(Node a, Node b) => a; Node M1() => null!; private static void Test(Node notNull, Node? possiblyNull) { _ = possiblyNull?.Next?.M1() ?? M2(possiblyNull = notNull, possiblyNull.Next = notNull); possiblyNull.Next.M1(); // incorrect warning } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(31905, "https://github.com/dotnet/roslyn/issues/31905")] public void NestedNullConditionalAccess4() { var source = @" public class C { public C? Nested; void Test1(C? c) => c?.Nested?.M(c.Nested.ToString()); void Test2(C? c) => c.Nested?.M(c.Nested.ToString()); void Test3(C c) => c?.Nested?.M(c.Nested.ToString()); void M(string s) => throw null!; }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,25): warning CS8602: Dereference of a possibly null reference. // void Test2(C? c) => c.Nested?.M(c.Nested.ToString()); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(7, 25) ); } [Fact] public void ConditionalAccess() { var source = @"class C { void M1(C c, C[] a) { _ = (c?.S).Length; _ = (a?[0]).P; } void M2(T t) where T : I { if (t == null) return; _ = (t?.S).Length; _ = (t?[0]).P; } int P { get => 0; } string S => throw null!; } interface I { string S { get; } C this[int i] { get; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,14): warning CS8602: Dereference of a possibly null reference. // _ = (c?.S).Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c?.S").WithLocation(5, 14), // (6,14): warning CS8602: Dereference of a possibly null reference. // _ = (a?[0]).P; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a?[0]").WithLocation(6, 14), // (11,14): warning CS8602: Dereference of a possibly null reference. // _ = (t?.S).Length; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t?.S").WithLocation(11, 14), // (12,14): warning CS8602: Dereference of a possibly null reference. // _ = (t?[0]).P; Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t?[0]").WithLocation(12, 14) ); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33615")] public void TestSubsituteMemberOfTuple() { var source = @"using System; class C { static void Main() { Console.WriteLine(Test(42)); } public static Test(object? a) { if (a == null) return; var x = (f1: a, f2: a); Func f = () => x.Test(a); f(); } } namespace System { public struct ValueTuple { public T1 Item1; public T2 Item2; public ValueTuple(T1 item1, T2 item2) { this.Item1 = item1; this.Item2 = item2; } public override string ToString() { return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; } public U Test(U val) { return val; } } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(33905, "https://github.com/dotnet/roslyn/issues/33905")] public void TestDiagnosticsInUnreachableCode() { var source = @"#pragma warning disable 0162 // suppress unreachable statement warning #pragma warning disable 0219 // suppress unused local warning class G { public static void Test(bool b, object? o, G g) { M1(o); // 1 M2(g); // 2 if (false) M1(o); if (false) M2(g); if (false && M1(o)) M2(g); if (false && M2(g)) M1(o); if (true || M1(o)) M2(g); // 3 if (true || M2(g)) M1(o); // 4 G g1 = g; // 5 if (false) { G g2 = g; } if (false) { object o1 = null; } } public static bool M1(object o) => true; public static bool M2(G o) => true; }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,12): warning CS8604: Possible null reference argument for parameter 'o' in 'bool G.M1(object o)'. // M1(o); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("o", "bool G.M1(object o)").WithLocation(7, 12), // (8,12): warning CS8620: Argument of type 'G' cannot be used as an input of type 'G' for parameter 'o' in 'bool G.M2(G o)' due to differences in the nullability of reference types. // M2(g); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "g").WithArguments("G", "G", "o", "bool G.M2(G o)").WithLocation(8, 12), // (14,16): warning CS8620: Argument of type 'G' cannot be used as an input of type 'G' for parameter 'o' in 'bool G.M2(G o)' due to differences in the nullability of reference types. // M2(g); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "g").WithArguments("G", "G", "o", "bool G.M2(G o)").WithLocation(14, 16), // (16,16): warning CS8604: Possible null reference argument for parameter 'o' in 'bool G.M1(object o)'. // M1(o); // 4 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "o").WithArguments("o", "bool G.M1(object o)").WithLocation(16, 16), // (17,24): warning CS8619: Nullability of reference types in value of type 'G' doesn't match target type 'G'. // G g1 = g; // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "g").WithArguments("G", "G").WithLocation(17, 24)); } [Fact] [WorkItem(33446, "https://github.com/dotnet/roslyn/issues/33446")] [WorkItem(34018, "https://github.com/dotnet/roslyn/issues/34018")] public void NullInferencesInFinallyClause() { var source = @"class Node { public Node? Next = null!; static void M1(Node node) { try { Mout(out node.Next); } finally { Mout(out node); // might set node to one in which node.Next == null } node.Next.ToString(); // 1 } static void M2() { Node? node = null; try { Mout(out node); } finally { if (node is null) {} else {} } node.ToString(); } static void M3() { Node? node = null; try { Mout(out node); } finally { node ??= node; } node.ToString(); } static void M4() { Node? node = null; try { Mout(out node); } finally { try { } finally { if (node is null) {} else {} } } node.ToString(); } static void M5() { Node? node = null; try { Mout(out node); } finally { try { if (node is null) {} else {} } finally { } } node.ToString(); } static void M6() { Node? node = null; try { Mout(out node); } finally { (node, _) = (null, node); } node.ToString(); // 2 } static void MN1() { Node? node = null; Mout(out node); if (node == null) {} else {} node.ToString(); // 3 } static void MN2() { Node? node = null; try { Mout(out node); } finally { if (node == null) {} else {} } node.ToString(); } static void Mout(out Node node) => node = null!; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,9): warning CS8602: Dereference of a possibly null reference. // node.Next.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "node.Next").WithLocation(15, 9), // (97,9): warning CS8602: Dereference of a possibly null reference. // node.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "node").WithLocation(97, 9), // (104,9): warning CS8602: Dereference of a possibly null reference. // node.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "node").WithLocation(104, 9)); } [Fact, WorkItem(32934, "https://github.com/dotnet/roslyn/issues/32934")] public void NoCycleInStructLayout() { var source = @" #nullable enable public struct Goo { public static Goo Bar; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(32446, "https://github.com/dotnet/roslyn/issues/32446")] public void RefValueOfNullableType() { var source = @" using System; public class C { public void M(TypedReference r) { _ = __refvalue(r, string?).Length; // 1 _ = __refvalue(r, string).Length; } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,13): warning CS8602: Dereference of a possibly null reference. // _ = __refvalue(r, string?).Length; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "__refvalue(r, string?)").WithLocation(7, 13) ); } [Fact, WorkItem(25375, "https://github.com/dotnet/roslyn/issues/25375")] public void ParamsNullable_SingleNullParam() { var source = @" class C { static void F(object x, params object?[] y) { } static void G(object x, params object[]? y) { } static void Main() { // Both calls here are invoked in normal form, not expanded F(string.Empty, null); // 1 G(string.Empty, null); // These are called with expanded form F(string.Empty, null, string.Empty); G(string.Empty, null, string.Empty); // 2 // Explicitly called with array F(string.Empty, new object?[] { null }); G(string.Empty, new object[] { null }); // 3 } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (16,25): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(string.Empty, null); // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 25), // (22,25): warning CS8625: Cannot convert null literal to non-nullable reference type. // G(string.Empty, null, string.Empty); // 2 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(22, 25), // (27,40): warning CS8625: Cannot convert null literal to non-nullable reference type. // G(string.Empty, new object[] { null }); // 3 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(27, 40) ); } [Fact, WorkItem(32172, "https://github.com/dotnet/roslyn/issues/32172")] public void NullableIgnored_InDisabledCode() { var source = @" #if UNDEF #nullable disable #endif #define DEF #if DEF #nullable disable // 1 #endif #if UNDEF #nullable enable #endif public class C { public void F(object o) { F(null); // no warning. '#nullable enable' in a disabled code region } } "; CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( // (9,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable disable // 1 Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(9, 2) ); CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()) .VerifyDiagnostics(); } [Fact, WorkItem(32172, "https://github.com/dotnet/roslyn/issues/32172")] public void DirectiveIgnored_InDisabledCode() { var source = @" #nullable disable warnings #if UNDEF #nullable restore warnings #endif public class C { public void F(object o) { F(null); // no warning. '#nullable restore warnings' in a disabled code region } } "; CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( // (2,2): error CS8652: The feature 'nullable reference types' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // #nullable disable warnings Diagnostic(ErrorCode.ERR_FeatureInPreview, "nullable").WithArguments("nullable reference types").WithLocation(2, 2)); CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()) .VerifyDiagnostics(); } [WorkItem(30987, "https://github.com/dotnet/roslyn/issues/30987")] [Fact] public void TypeInference_LowerBounds_TopLevelNullability_03() { var source = @"using System; class C { static T F(T x, T y) => x; static void G1(A x, B? y) { F(x, x)/*T:A!*/; F(x, y)/*T:A?*/; F(y, x)/*T:A?*/; F(y, y)/*T:B?*/; } static void G2(A x, B? y) { _ = new [] { x, x }[0]/*T:A!*/; _ = new [] { x, y }[0]/*T:A?*/; _ = new [] { y, x }[0]/*T:A?*/; _ = new [] { y, y }[0]/*T:B?*/; } static T M(Func func) => func(); static void G3(bool b, A x, B? y) { M(() => { if (b) return x; return x; })/*T:A!*/; M(() => { if (b) return x; return y; })/*T:A?*/; M(() => { if (b) return y; return x; })/*T:A?*/; M(() => { if (b) return y; return y; })/*T:B?*/; } static void G4(bool b, A x, B? y) { _ = (b ? x : x)/*T:A!*/; _ = (b ? x : y)/*T:A?*/; _ = (b ? y : x)/*T:A?*/; _ = (b ? y : y)/*T:B?*/; } } class A { } class B : A { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(30987, "https://github.com/dotnet/roslyn/issues/30987")] [Fact] public void TypeInference_LowerBounds_TopLevelNullability_04() { var source = @"class D { static T F(T x, T y, T z) => x; static void G1(A x, B? y, C z) { F(x, y, z)/*T:A?*/; F(y, z, x)/*T:A?*/; F(z, x, y)/*T:A?*/; F(x, z, y)/*T:A?*/; F(z, y, x)/*T:A?*/; F(y, x, z)/*T:A?*/; } } class A { } class B : A { } class C : A { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); comp.VerifyTypes(); } [WorkItem(30987, "https://github.com/dotnet/roslyn/issues/30987")] [Fact] public void TypeInference_LowerBounds_TopLevelNullability_05() { var source = @"class D { #nullable disable static T F(T x, T y, T z) => x; static void G1(A x, B? y, C z) #nullable enable { F(x, y, z)/*T:A?*/; F(y, z, x)/*T:A?*/; F(z, x, y)/*T:A?*/; F(x, z, y)/*T:A?*/; F(z, y, x)/*T:A?*/; F(y, x, z)/*T:A?*/; } } class A { } class B : A { } class C : A { } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (5,26): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // static void G1(A x, B? y, C z) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 26)); comp.VerifyTypes(); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_01() { var source = @"using System; class C { static T F(Func f) => throw null!; static void G(object? o) { F(() => o).ToString(); // warning: maybe null if (o == null) return; F(() => o).ToString(); // no warning } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,9): warning CS8602: Dereference of a possibly null reference. // F(() => o).ToString(); // warning: maybe null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => o)").WithLocation(8, 9)); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_02() { var source = @"using System; class C { static bool M(object? o) => throw null!; static T F(Func f, bool ignored) => throw null!; static void G(object? o) { F(() => o, M(1)).ToString(); // warning: maybe null if (o == null) return; F(() => o, M(o = null)).ToString(); // no warning } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // F(() => o, M(1)).ToString(); // warning: maybe null Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => o, M(1))").WithLocation(9, 9)); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_03() { var source = @"using System; class C { static bool M(object? o) => throw null!; static Func F(Func f, bool ignored = false) => throw null!; static void G(object? o) { var fa1 = new[] { F(() => o), F(() => o, M(o = null)) }; fa1[0]().ToString(); // warning if (o == null) return; var fa2 = new[] { F(() => o), F(() => o, M(o = null)) }; fa2[0]().ToString(); if (o == null) return; var fa3 = new[] { F(() => o, M(o = null)), F(() => o) }; fa3[0]().ToString(); // warning } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,9): warning CS8602: Dereference of a possibly null reference. // fa1[0]().ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "fa1[0]()").WithLocation(10, 9), // (18,9): warning CS8602: Dereference of a possibly null reference. // fa3[0]().ToString(); // warning Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "fa3[0]()").WithLocation(18, 9)); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_04() { var source = @"using System; class C { static T F(Func f) => throw null!; static void G(object? o) { F((Func)(() => o)).ToString(); // 1 if (o == null) return; F((Func)(() => o)).ToString(); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (8,32): warning CS8603: Possible null reference return. // F((Func)(() => o)).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(8, 32)); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_05() { var source = @"using System; class C { static T F(Func f) => throw null!; static void G(Action a) => throw null!; static void M(object? o) { F(() => o).ToString(); // 1 if (o == null) return; F(() => o).ToString(); G(() => o = null); // does not affect state in caller F(() => o).ToString(); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (9,9): warning CS8602: Dereference of a possibly null reference. // F(() => o).ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F(() => o)").WithLocation(9, 9)); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_06() { var source = @"using System; class C { static T F(object? o, params Func[] a) => throw null!; static void M(string? x) { F(x = """", () => x = null, () => x.ToString()); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(29617, "https://github.com/dotnet/roslyn/issues/29617")] public void CaptureVariablesWhereLambdaAppears_07() { var source = @"using System; class C { static T F([System.Diagnostics.CodeAnalysis.NotNull] object? o, params Func[] a) => throw null!; static void M(string? x) { F(x = """", () => x = null, () => x.ToString()); } } "; var comp = CreateCompilation(new[] { source, NotNullAttributeDefinition }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact] [WorkItem(34841, "https://github.com/dotnet/roslyn/issues/34841")] public void PartialClassWithConstraints_01() { var source1 = @"#nullable enable using System; partial class C where T : IEquatable, new() { }"; var source2 = @"using System; partial class C where T : IEquatable, new() { }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source2, source1 }); comp.VerifyDiagnostics(); validate(); void validate() { var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.Equal("System.IEquatable!", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } } [Fact] [WorkItem(34841, "https://github.com/dotnet/roslyn/issues/34841")] public void PartialClassWithConstraints_02() { var source1 = @"#nullable enable using System; partial class C where T : class?, IEquatable, new() { }"; var source2 = @"using System; partial class C where T : class, IEquatable, new() { }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source2, source1 }); comp.VerifyDiagnostics(); validate(); void validate() { var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.True(t.ReferenceTypeConstraintIsNullable); Assert.Equal("System.IEquatable!", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } } [Fact] [WorkItem(34841, "https://github.com/dotnet/roslyn/issues/34841")] public void PartialClassWithConstraints_03() { var source1 = @"#nullable enable using System; class C where T : IEquatable { }"; var source2 = @"using System; class C where T : IEquatable { }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics( // (2,7): error CS0101: The namespace '' already contains a definition for 'C' // class C where T : IEquatable Diagnostic(ErrorCode.ERR_DuplicateNameInNS, "C").WithArguments("C", "").WithLocation(2, 7) ); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("System.IEquatable!", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } [Fact] public void PartialClassWithConstraints_04() { var source1 = @" using System; partial class C where T : IEquatable< #nullable enable string? #nullable disable > { }"; var source2 = @"using System; partial class C where T : IEquatable? #nullable disable { }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source2, source1 }); comp.VerifyDiagnostics(); validate(); void validate() { var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("System.IEquatable?", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } } [Fact] public void PartialClassWithConstraints_05() { var source1 = @"#nullable enable partial class C where T : class, new() { }"; var source2 = @" partial class C where T : class, new() { }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source2, source1 }); comp.VerifyDiagnostics(); validate(); void validate() { var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.False(t.ReferenceTypeConstraintIsNullable); } } [Fact] public void PartialClassWithConstraints_06() { var source1 = @"#nullable enable partial class C where T : class, new() { } partial class C where T : class, new() { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics(); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.False(t.ReferenceTypeConstraintIsNullable); } [Fact] public void PartialClassWithConstraints_07() { var source1 = @"#nullable enable partial class C where T : class?, new() { } partial class C where T : class?, new() { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics(); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.True(t.ReferenceTypeConstraintIsNullable); } [Fact] public void PartialClassWithConstraints_08() { var source1 = @"#nullable disable partial class C where T : class, new() { } partial class C where T : class, new() { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics(); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.Null(t.ReferenceTypeConstraintIsNullable); } [Fact] public void PartialClassWithConstraints_09() { var source1 = @"#nullable enable partial class C where T : class?, new() { } partial class C where T : class, new() { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics( // (2,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : class?, new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(2, 15) ); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.True(t.ReferenceTypeConstraintIsNullable); } [Fact] public void PartialClassWithConstraints_10() { var source1 = @"#nullable enable partial class C where T : class, new() { } partial class C where T : class?, new() { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics( // (2,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : class, new() Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(2, 15) ); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.True(t.HasConstructorConstraint); Assert.True(t.HasReferenceTypeConstraint); Assert.False(t.ReferenceTypeConstraintIsNullable); } [Fact] public void PartialClassWithConstraints_11() { var source1 = @"#nullable enable using System; partial class C where T : IEquatable? { } partial class C where T : IEquatable { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics( // (3,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : IEquatable? Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(3, 15) ); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("System.IEquatable?", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } [Fact] public void PartialClassWithConstraints_12() { var source1 = @"#nullable enable using System; partial class C where T : IEquatable { } partial class C where T : IEquatable? { }"; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics( // (3,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : IEquatable Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(3, 15) ); var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("System.IEquatable!", t.ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } [Fact] public void PartialClassWithConstraints_13() { var source1 = @"#nullable enable using System; partial class C where T : class, IEquatable?, IEquatable { } "; var source2 = @"using System; partial class C where T : class, IEquatable, IEquatable { }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); validate(0, 1); comp = CreateCompilation(new[] { source2, source1 }); comp.VerifyDiagnostics(); validate(1, 0); void validate(int i, int j) { var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("System.IEquatable?", t.ConstraintTypesNoUseSiteDiagnostics[i].ToTestDisplayString(true)); Assert.Equal("System.IEquatable!", t.ConstraintTypesNoUseSiteDiagnostics[j].ToTestDisplayString(true)); } } [Fact] public void PartialClassWithConstraints_14() { var source0 = @" interface I1 { } "; var source1 = @" partial class C where T : I1< #nullable enable string?, #nullable disable string> { } "; var source2 = @" partial class C where T : I1 { } "; var source3 = @" partial class C where T : I1? #nullable disable { } "; var comp1 = CreateCompilation(new[] { source0, source1 }); comp1.VerifyDiagnostics(); var c = comp1.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("I1", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); var comp2 = CreateCompilation(new[] { source0, source2 }); comp2.VerifyDiagnostics(); c = comp2.GlobalNamespace.GetTypeMember("C"); t = c.TypeParameters[0]; Assert.Equal("I1", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); var comp3 = CreateCompilation(new[] { source0, source3 }); comp3.VerifyDiagnostics(); c = comp3.GlobalNamespace.GetTypeMember("C"); t = c.TypeParameters[0]; Assert.Equal("I1?", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); var comp = CreateCompilation(new[] { source0, source1, source2, source3 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source0, source1, source3, source2 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source0, source2, source1, source3 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source0, source2, source3, source1 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source0, source3, source1, source2 }); comp.VerifyDiagnostics(); validate(); comp = CreateCompilation(new[] { source0, source3, source2, source1 }); comp.VerifyDiagnostics(); validate(); void validate() { var c = comp.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("I1?", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } } [Fact] public void PartialClassWithConstraints_15() { var source = @" interface I1 { } interface I2 { } #nullable enable partial class C where T : I1?, #nullable disable I2 { } #nullable enable partial class C where T : I1, I2? { } "; var comp1 = CreateCompilation(new[] { source }); comp1.VerifyDiagnostics( // (12,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : I1?, Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(12, 15) ); var c = comp1.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("I1?", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); Assert.Equal("I2?", t.ConstraintTypesNoUseSiteDiagnostics[1].ToTestDisplayString(true)); } [Fact] public void PartialClassWithConstraints_16() { var source = @" interface I1 { } interface I2 { } #nullable enable partial class C where T : I1, #nullable disable I2 { } #nullable enable partial class C where T : I1?, I2 { } "; var comp1 = CreateCompilation(new[] { source }); comp1.VerifyDiagnostics( // (12,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : I1, Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(12, 15) ); var c = comp1.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("I1!", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); Assert.Equal("I2!", t.ConstraintTypesNoUseSiteDiagnostics[1].ToTestDisplayString(true)); } [Fact] public void PartialClassWithConstraints_17() { var source = @" interface I1 { } interface I2 { } #nullable disable partial class C where T : I1, #nullable enable I2? { } partial class C where T : I1?, I2 { } "; var comp1 = CreateCompilation(new[] { source }); comp1.VerifyDiagnostics( // (12,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : I1, Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(12, 15) ); var c = comp1.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("I1?", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); Assert.Equal("I2?", t.ConstraintTypesNoUseSiteDiagnostics[1].ToTestDisplayString(true)); } [Fact] public void PartialClassWithConstraints_18() { var source = @" interface I1 { } interface I2 { } #nullable disable partial class C where T : I1, #nullable enable I2 { } partial class C where T : I1, I2? { } "; var comp1 = CreateCompilation(new[] { source }); comp1.VerifyDiagnostics( // (12,15): error CS0265: Partial declarations of 'C' have inconsistent constraints for type parameter 'T' // partial class C where T : I1, Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "C").WithArguments("C", "T").WithLocation(12, 15) ); var c = comp1.GlobalNamespace.GetTypeMember("C"); TypeParameterSymbol t = c.TypeParameters[0]; Assert.Equal("I1!", t.ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); Assert.Equal("I2!", t.ConstraintTypesNoUseSiteDiagnostics[1].ToTestDisplayString(true)); } [Fact] public void PartialInterfacesWithConstraints_01() { var source = @" #nullable enable interface I1 { } partial interface I1 where T : I1 {} partial interface I1 where T : I1? {} partial interface I2 where T : I1? {} partial interface I2 where T : I1 {} partial interface I3 where T : I1 {} partial interface I3 where T : I1? {} partial interface I4 where T : I1? {} partial interface I4 where T : I1 {} "; var comp1 = CreateCompilation(new[] { source }); comp1.VerifyDiagnostics( // (8,19): error CS0265: Partial declarations of 'I1' have inconsistent constraints for type parameter 'T' // partial interface I1 where T : I1 Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I1").WithArguments("I1", "T").WithLocation(8, 19), // (14,19): error CS0265: Partial declarations of 'I2' have inconsistent constraints for type parameter 'T' // partial interface I2 where T : I1? Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I2").WithArguments("I2", "T").WithLocation(14, 19), // (20,19): error CS0265: Partial declarations of 'I3' have inconsistent constraints for type parameter 'T' // partial interface I3 where T : I1 Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I3").WithArguments("I3", "T").WithLocation(20, 19), // (26,19): error CS0265: Partial declarations of 'I4' have inconsistent constraints for type parameter 'T' // partial interface I4 where T : I1? Diagnostic(ErrorCode.ERR_PartialWrongConstraints, "I4").WithArguments("I4", "T").WithLocation(26, 19) ); } [Fact] public void PartialMethodsWithConstraints_01() { var source1 = @"#nullable enable using System; partial class C { static partial void F() where T : IEquatable; }"; var source2 = @"using System; partial class C { static partial void F() where T : IEquatable { } }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); var f = comp.GlobalNamespace.GetMember("C.F"); Assert.Equal("System.IEquatable!", f.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); Assert.Equal("System.IEquatable", f.PartialImplementationPart.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } [Fact] public void PartialMethodsWithConstraints_02() { var source1 = @"#nullable enable using System; partial class C { static partial void F() where T : class?, IEquatable; }"; var source2 = @"using System; partial class C { static partial void F() where T : class, IEquatable { } }"; var comp = CreateCompilation(new[] { source1, source2 }); comp.VerifyDiagnostics(); var f = comp.GlobalNamespace.GetMember("C.F"); Assert.True(f.TypeParameters[0].ReferenceTypeConstraintIsNullable); Assert.Equal("System.IEquatable!", f.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); Assert.Null(f.PartialImplementationPart.TypeParameters[0].ReferenceTypeConstraintIsNullable); Assert.Equal("System.IEquatable", f.PartialImplementationPart.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics.Single().ToTestDisplayString(true)); } [Fact] [WorkItem(35227, "https://github.com/dotnet/roslyn/issues/35227")] public void PartialMethodsWithConstraints_03() { var source1 = @" partial class C { #nullable enable static partial void F(I x) where T : class; #nullable disable static partial void F(I x) where T : class #nullable enable { Test2(x); } void Test1() where U : class? { F(null); } static void Test2(I x) where S : class { } } interface I { } "; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics( // (16,9): warning CS8634: The type 'U' cannot be used as type parameter 'T' in the generic type or method 'C.F(I)'. Nullability of type argument 'U' doesn't match 'class' constraint. // F(null); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "F").WithArguments("C.F(I)", "T", "U").WithLocation(16, 9), // (16,14): warning CS8625: Cannot convert null literal to non-nullable reference type. // F(null); Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 14) ); } [Fact] [WorkItem(35227, "https://github.com/dotnet/roslyn/issues/35227")] public void PartialMethodsWithConstraints_04() { var source1 = @" partial class C { #nullable disable static partial void F(I x) where T : class; #nullable enable static partial void F(I x) where T : class { Test2(x); } void Test1() where U : class? { F(null); } static void Test2(I x) where S : class { } } interface I { } "; var comp = CreateCompilation(new[] { source1 }); comp.VerifyDiagnostics( // (10,15): warning CS8620: Argument of type 'I' cannot be used for parameter 'x' of type 'I' in 'void C.Test2(I x)' due to differences in the nullability of reference types. // Test2(x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("I", "I", "x", "void C.Test2(I x)").WithLocation(10, 15) ); } [Fact] public void TestExplicitImplementationAmbiguousInterfaceMethod_DifferingNullabilityAnnotations1() { var text = @" #nullable enable public interface Interface where T : class { void Method(string i); void Method(T? i); } public class Class : Interface { void Interface.Method(string i) { } //this explicitly implements both methods in Interface public void Method(string i) { } //this is here to avoid CS0535 - not implementing interface method } "; CreateCompilation(text).VerifyDiagnostics( // (11,28): warning CS0473: Explicit interface implementation 'Class.Interface.Method(string)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead. // void Interface.Method(string i) { } //this explicitly implements both methods in Interface Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Class.Interface.Method(string)").WithLocation(11, 28), // (12,17): warning CS8614: Nullability of reference types in type of parameter 'i' of 'void Class.Method(string i)' doesn't match implicitly implemented member 'void Interface.Method(string? i)'. // public void Method(string i) { } //this is here to avoid CS0535 - not implementing interface method Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "Method").WithArguments("i", "void Class.Method(string i)", "void Interface.Method(string? i)").WithLocation(12, 17)); } [Fact] public void TestExplicitImplementationAmbiguousInterfaceMethod_DifferingNullabilityAnnotations2() { var text = @" #nullable enable public interface Interface where T : class { void Method(string i); void Method(T? i); } public class Class : Interface { void Interface.Method(string? i) { } //this explicitly implements both methods in Interface public void Method(string i) { } //this is here to avoid CS0535 - not implementing interface method } "; CreateCompilation(text).VerifyDiagnostics( // (11,28): warning CS0473: Explicit interface implementation 'Class.Interface.Method(string?)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead. // void Interface.Method(string? i) { } //this explicitly implements both methods in Interface Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Class.Interface.Method(string?)").WithLocation(11, 28), // (12,17): warning CS8614: Nullability of reference types in type of parameter 'i' of 'void Class.Method(string i)' doesn't match implicitly implemented member 'void Interface.Method(string? i)'. // public void Method(string i) { } //this is here to avoid CS0535 - not implementing interface method Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "Method").WithArguments("i", "void Class.Method(string i)", "void Interface.Method(string? i)").WithLocation(12, 17)); } [Fact] public void TestExplicitImplementationAmbiguousInterfaceMethod_DifferingNullabilityAnnotations3() { var text = @" #nullable enable public interface Interface where T : class { void Method(string? i); void Method(T i); } public class Class : Interface { void Interface.Method(string i) { } //this explicitly implements both methods in Interface public void Method(string? i) { } //this is here to avoid CS0535 - not implementing interface method } "; CreateCompilation(text).VerifyDiagnostics( // (11,28): warning CS0473: Explicit interface implementation 'Class.Interface.Method(string)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead. // void Interface.Method(string i) { } //this explicitly implements both methods in Interface Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Class.Interface.Method(string)").WithLocation(11, 28), // (11,28): warning CS8617: Nullability of reference types in type of parameter 'i' doesn't match implemented member 'void Interface.Method(string? i)'. // void Interface.Method(string i) { } //this explicitly implements both methods in Interface Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "Method").WithArguments("i", "void Interface.Method(string? i)").WithLocation(11, 28) ); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ImplementMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter() { var source = @" #nullable enable interface I { void Goo(T? value) where T : class; } class C1 : I { public void Goo(T? value) where T : class { } } class C2 : I { void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (13,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(13, 12), // (15,12): error CS0539: 'C2.Goo(T?)' in explicit interface declaration is not found among members of the interface that can be implemented // void I.Goo(T? value) { } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C2.Goo(T?)").WithLocation(15, 12), // (15,22): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // void I.Goo(T? value) { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "value").WithArguments("System.Nullable", "T", "T").WithLocation(15, 22)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ImplementMethodTakingNonNullableClassParameter_WithMethodTakingNullableClassParameter() { var source = @" #nullable enable interface I { void Goo(T value) where T : class; } class C1 : I { public void Goo(T? value) where T : class { } } class C2 : I { void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (13,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T)").WithLocation(13, 12), // (15,12): error CS0539: 'C2.Goo(T?)' in explicit interface declaration is not found among members of the interface that can be implemented // void I.Goo(T? value) { } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C2.Goo(T?)").WithLocation(15, 12), // (15,22): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // void I.Goo(T? value) { } Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "value").WithArguments("System.Nullable", "T", "T").WithLocation(15, 22)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ImplementMethodTakingNullableClassParameter_WithMethodTakingNonNullableClassParameter() { var source = @" #nullable enable interface I { void Goo(T? value) where T : class; } class C1 : I { public void Goo(T value) where T : class { } } class C2 : I { void I.Goo(T value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (10,17): warning CS8614: Nullability of reference types in type of parameter 'value' of 'void C1.Goo(T value)' doesn't match implicitly implemented member 'void I.Goo(T? value)'. // public void Goo(T value) where T : class { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "Goo").WithArguments("value", "void C1.Goo(T value)", "void I.Goo(T? value)").WithLocation(10, 17), // (15,12): warning CS8617: Nullability of reference types in type of parameter 'value' doesn't match implemented member 'void I.Goo(T? value)'. // void I.Goo(T value) { } Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation, "Goo").WithArguments("value", "void I.Goo(T? value)").WithLocation(15, 12)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ExplicitImplementationOverloadAcceptingNullableT() { var source = @" interface I { void Goo(T value); void Goo(T? value) where T : struct; } class C1 : I { public void Goo(T value) { } public void Goo(T? value) where T : struct { } } class C2 : I { void I.Goo(T value) { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ExplicitImplementationOverloadAcceptingNullableT_OppositeDeclarationOrder() { var source = @" interface I { void Goo(T? value) where T : struct; void Goo(T value); } class C1 : I { public void Goo(T value) { } public void Goo(T? value) where T : struct { } } class C2 : I { void I.Goo(T value) { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ExplicitImplementationOverloadAcceptingNullableT_WithClassConstraint() { var source = @" #nullable enable interface I { void Goo(T value) where T : class; void Goo(T? value) where T : struct; } class C1 : I { public void Goo(T value) where T : class { } public void Goo(T? value) where T : struct { } } class C2 : I { void I.Goo(T value) { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ExplicitImplementationOverloadAcceptingNullableT_ReturnTypesDoNotMatchNullabilityModifiers() { var source = @" #nullable enable interface I where U : class { U Goo(T value); U Goo(T? value) where T : struct; } class C1 : I where U : class { public U? Goo(T value) => default; public U? Goo(T? value) where T : struct => default; } class C2 : I where U : class { U? I.Goo(T value) => default; U? I.Goo(T? value) => default; } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (11,15): warning CS8613: Nullability of reference types in return type of 'U? C1.Goo(T value)' doesn't match implicitly implemented member 'U I.Goo(T value)'. // public U? Goo(T value) => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "Goo").WithArguments("U? C1.Goo(T value)", "U I.Goo(T value)").WithLocation(11, 15), // (12,15): warning CS8613: Nullability of reference types in return type of 'U? C1.Goo(T? value)' doesn't match implicitly implemented member 'U I.Goo(T? value)'. // public U? Goo(T? value) where T : struct => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "Goo").WithArguments("U? C1.Goo(T? value)", "U I.Goo(T? value)").WithLocation(12, 15), // (17,13): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'U I.Goo(T value)'. // U? I.Goo(T value) => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "Goo").WithArguments("U I.Goo(T value)").WithLocation(17, 13), // (18,13): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'U I.Goo(T? value)'. // U? I.Goo(T? value) => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "Goo").WithArguments("U I.Goo(T? value)").WithLocation(18, 13)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void ExplicitImplementationOverloadAcceptingNullableT_ReturnTypesDoNotMatchNullabilityModifiers_OppositeDeclarationOrder() { var source = @" #nullable enable interface I where U : class { U Goo(T? value) where T : struct; U Goo(T value); } class C1 : I where U : class { public U? Goo(T value) => default; public U? Goo(T? value) where T : struct => default; } class C2 : I where U : class { U? I.Goo(T value) => default; U? I.Goo(T? value) => default; } "; //As a result of https://github.com/dotnet/roslyn/issues/34583 these don't test anything useful at the moment var comp = CreateCompilation(source).VerifyDiagnostics( // (11,15): warning CS8613: Nullability of reference types in return type of 'U? C1.Goo(T value)' doesn't match implicitly implemented member 'U I.Goo(T value)'. // public U? Goo(T value) => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "Goo").WithArguments("U? C1.Goo(T value)", "U I.Goo(T value)").WithLocation(11, 15), // (12,15): warning CS8613: Nullability of reference types in return type of 'U? C1.Goo(T? value)' doesn't match implicitly implemented member 'U I.Goo(T? value)'. // public U? Goo(T? value) where T : struct => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "Goo").WithArguments("U? C1.Goo(T? value)", "U I.Goo(T? value)").WithLocation(12, 15), // (17,13): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'U I.Goo(T value)'. // U? I.Goo(T value) => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "Goo").WithArguments("U I.Goo(T value)").WithLocation(17, 13), // (18,13): warning CS8616: Nullability of reference types in return type doesn't match implemented member 'U I.Goo(T? value)'. // U? I.Goo(T? value) => default; Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation, "Goo").WithArguments("U I.Goo(T? value)").WithLocation(18, 13)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation() { var source = @" #nullable enable interface I { void Goo(T? value) where T : class; void Goo(T? value) where T : struct; } class C2 : I { void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(9, 12)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_WithImplicitOverrideOfStructMember() { var source = @" #nullable enable interface I { void Goo(T? value) where T : class; void Goo(T? value) where T : struct; } class C2 : I { public void Goo(T? value) where T : struct { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(9, 12)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_WithImplicitOverrideOfClassMember() { var source = @" #nullable enable interface I { void Goo(T? value) where T : class; void Goo(T? value) where T : struct; } class C2 : I { public void Goo(T? value) where T : class { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_WithImplicitOverrideOfStructMember_OppositeDeclarationOrder() { var source = @" #nullable enable interface I { void Goo(T? value) where T : struct; void Goo(T? value) where T : class; } class C2 : I { public void Goo(T? value) where T : struct { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(9, 12)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_WithImplicitOverrideOfClassMember_OppositeDeclarationOrder() { var source = @" #nullable enable interface I { void Goo(T? value) where T : struct; void Goo(T? value) where T : class; } class C2 : I { public void Goo(T? value) where T : class { } void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_OppositeDeclarationOrder() { var source = @" #nullable enable interface I { void Goo(T? value) where T : struct; void Goo(T? value) where T : class; } class C2 : I { void I.Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(9, 12)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_DifferingReturnType() { var source = @" #nullable enable interface I { string Goo(T? value) where T : class; int Goo(T? value) where T : struct; } class C2 : I { int I.Goo(T? value) => 42; string I.Goo(T? value) => ""42""; } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(9, 12), // (12,14): error CS0539: 'C2.Goo(T?)' in explicit interface declaration is not found among members of the interface that can be implemented // string I.Goo(T? value) => "42"; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C2.Goo(T?)").WithLocation(12, 14), // (12,24): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable' // string I.Goo(T? value) => "42"; Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "value").WithArguments("System.Nullable", "T", "T").WithLocation(12, 24)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void AmbiguousExplicitInterfaceImplementation_ReturnTypeDifferingInNullabilityAnotation() { var source = @" #nullable enable interface I { object Goo(T? value) where T : class; object? Goo(T? value) where T : struct; } class C2 : I { object I.Goo(T? value) => 42; object? I.Goo(T? value) => 42; } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,7): error CS8646: 'I.Goo(T?)' is explicitly implemented more than once. // class C2 : I Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C2").WithArguments("I.Goo(T?)").WithLocation(9, 7), // (9,12): error CS0535: 'C2' does not implement interface member 'I.Goo(T?)' // class C2 : I Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C2", "I.Goo(T?)").WithLocation(9, 12), // (12,15): error CS0111: Type 'C2' already defines a member called 'I.Goo' with the same parameter types // object? I.Goo(T? value) => 42; Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Goo").WithArguments("I.Goo", "C2").WithLocation(12, 15)); } [Fact] [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")] public void OverrideMethodTakingNullableClassTypeParameterDefinedByClass_WithMethodTakingNullableClassParameter() { var source = @" #nullable enable abstract class Base where T : class { public abstract void Goo(T? value); } class Derived : Base where T : class { public override void Goo(T? value) { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.False(dGoo.Parameters[0].Type.IsNullableType()); Assert.True(dGoo.Parameters[0].TypeWithAnnotations.NullableAnnotation == NullableAnnotation.Annotated); } [Fact] public void ImplementMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter1() { var source = @" #nullable enable interface I { void Goo(T? value) where T : class; } class C1 : I { public void Goo(T? value) where T : class { } } class C2 : I { void I.Goo(T? value) where T : class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo"); Assert.True(c2Goo.Parameters[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, c2Goo.Parameters[0].TypeWithAnnotations.NullableAnnotation); } [Fact] public void ImplementMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter2() { var source = @" #nullable enable interface I { void Goo(T?[] value) where T : class; } class C1 : I { public void Goo(T?[] value) where T : class { } } class C2 : I { void I.Goo(T?[] value) where T : class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo"); Assert.True(((ArrayTypeSymbol)c2Goo.Parameters[0].Type).ElementType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, ((ArrayTypeSymbol)c2Goo.Parameters[0].Type).ElementTypeWithAnnotations.NullableAnnotation); } [Fact] public void ImplementMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter3() { var source = @" #nullable enable interface I { void Goo((T a, T? b)? value) where T : class; } class C1 : I { public void Goo((T a, T? b)? value) where T : class { } } class C2 : I { void I.Goo((T a, T? b)? value) where T : class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo"); Assert.True(c2Goo.Parameters[0].Type.IsNullableType()); var tuple = c2Goo.Parameters[0].Type.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0]; Assert.True(tuple.TupleElements[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.NotAnnotated, tuple.TupleElements[0].TypeWithAnnotations.NullableAnnotation); Assert.True(tuple.TupleElements[1].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, tuple.TupleElements[1].TypeWithAnnotations.NullableAnnotation); } [Fact] public void ImplementMethodReturningNullableClassParameter_WithMethodReturningNullableClass1() { var source = @" #nullable enable interface I { T? Goo() where T : class; } class C1 : I { public T? Goo() where T : class => default; } class C2 : I { T? I.Goo() where T : class => default; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo"); Assert.True(c2Goo.ReturnType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, c2Goo.ReturnTypeWithAnnotations.NullableAnnotation); } [Fact] public void ImplementMethodReturningNullableClassParameter_WithMethodReturningNullableClass2() { var source = @" #nullable enable interface I { T?[] Goo() where T : class; } class C1 : I { public T?[] Goo() where T : class => default!; } class C2 : I { T?[] I.Goo() where T : class => default!; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo"); Assert.True(((ArrayTypeSymbol)c2Goo.ReturnType).ElementType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, ((ArrayTypeSymbol)c2Goo.ReturnType).ElementTypeWithAnnotations.NullableAnnotation); } [Fact] public void ImplementMethodReturningNullableClassParameter_WithMethodReturningNullableClass3() { var source = @" #nullable enable interface I { (T a, T? b)? Goo() where T : class; } class C1 : I { public (T a, T? b)? Goo() where T : class => default; } class C2 : I { (T a, T? b)? I.Goo() where T : class => default; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo"); Assert.True(c2Goo.ReturnType.IsNullableType()); var tuple = c2Goo.ReturnType.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0]; Assert.True(tuple.TupleElements[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.NotAnnotated, tuple.TupleElements[0].TypeWithAnnotations.NullableAnnotation); Assert.True(tuple.TupleElements[1].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, tuple.TupleElements[1].TypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter1() { var source = @" #nullable enable abstract class Base { public abstract void Goo(T? value) where T : class; } class Derived : Base { public override void Goo(T? value) where T : class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(dGoo.Parameters[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, dGoo.Parameters[0].TypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter2() { var source = @" #nullable enable abstract class Base { public abstract void Goo(T?[] value) where T : class; } class Derived : Base { public override void Goo(T?[] value) where T : class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(((ArrayTypeSymbol)dGoo.Parameters[0].Type).ElementType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, ((ArrayTypeSymbol)dGoo.Parameters[0].Type).ElementTypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethodTakingNullableClassParameter_WithMethodTakingNullableClassParameter3() { var source = @" #nullable enable abstract class Base { public abstract void Goo((T a, T? b)? value) where T : class; } class Derived : Base { public override void Goo((T a, T? b)? value) where T : class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(dGoo.Parameters[0].Type.IsNullableType()); var tuple = dGoo.Parameters[0].Type.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0]; Assert.True(tuple.TupleElements[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.NotAnnotated, tuple.TupleElements[0].TypeWithAnnotations.NullableAnnotation); Assert.True(tuple.TupleElements[1].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, tuple.TupleElements[1].TypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethodReturningNullableClassParameter_WithMethodReturningNullableClass1() { var source = @" #nullable enable abstract class Base { public abstract T? Goo() where T : class; } class Derived : Base { public override T? Goo() where T : class => default; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(dGoo.ReturnType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, dGoo.ReturnTypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethodReturningNullableClassParameter_WithMethodReturningNullableClass2() { var source = @" #nullable enable abstract class Base { public abstract T?[] Goo() where T : class; } class Derived : Base { public override T?[] Goo() where T : class => default!; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(((ArrayTypeSymbol)dGoo.ReturnType).ElementType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, ((ArrayTypeSymbol)dGoo.ReturnType).ElementTypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethodReturningNullableClassParameter_WithMethodReturningNullableClass3() { var source = @" #nullable enable abstract class Base { public abstract (T a, T? b)? Goo() where T : class; } class Derived : Base { public override (T a, T? b)? Goo() where T : class => default; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(dGoo.ReturnType.IsNullableType()); var tuple = dGoo.ReturnType.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0]; Assert.True(tuple.TupleElements[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.NotAnnotated, tuple.TupleElements[0].TypeWithAnnotations.NullableAnnotation); Assert.True(tuple.TupleElements[1].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, tuple.TupleElements[1].TypeWithAnnotations.NullableAnnotation); } [Fact] public void OverrideMethod_WithMultipleClassAndStructConstraints() { var source = @" using System.IO; #nullable enable abstract class Base { public abstract T? Goo(U? u, (V?, U?) vu) where T : Stream where U : struct where V : class; } class Derived : Base { public override T? Goo(U? u, (V?, U?) vu) where T : class where U : struct where V : class => default!; } "; var comp = CreateCompilation(source).VerifyDiagnostics(); var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo"); Assert.True(dGoo.ReturnType.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, dGoo.ReturnTypeWithAnnotations.NullableAnnotation); Assert.True(dGoo.Parameters[0].Type.IsNullableType()); var tuple = dGoo.Parameters[1].Type; Assert.True(tuple.TupleElements[0].Type.IsReferenceType); Assert.Equal(NullableAnnotation.Annotated, tuple.TupleElements[0].TypeWithAnnotations.NullableAnnotation); Assert.True(tuple.TupleElements[1].Type.IsNullableType()); } [Fact] [WorkItem(29894, "https://github.com/dotnet/roslyn/issues/29894")] public void TypeOf_03() { var source = @" #nullable enable class K { } class C1 { object o1 = typeof(int); object o2 = typeof(string); object o3 = typeof(int?); object o4 = typeof(string?); // 1 object o5 = typeof(K); object o6 = typeof(K); object o7 = typeof(K?); // 2 object o8 = typeof(K?);// 3 } #nullable disable class C2 { object o1 = typeof(int); object o2 = typeof(string); object o3 = typeof(int?); object o4 = typeof(string?); // 4, 5 object o5 = typeof(K); object o6 = typeof(K); // 6 object o7 = typeof(K?); // 7, 8 object o8 = typeof(K?);// 9, 10, 11 } #nullable enable class C3 where TClass : class where TStruct : struct { object o1 = typeof(T?); // 12 object o2 = typeof(TClass?); // 13 object o3 = typeof(TStruct?); } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (9,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o4 = typeof(string?); // 1 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(string?)").WithLocation(9, 17), // (12,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o7 = typeof(K?); // 2 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(K?)").WithLocation(12, 17), // (13,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o8 = typeof(K?);// 3 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(K?)").WithLocation(13, 17), // (21,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o4 = typeof(string?); // 4, 5 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(string?)").WithLocation(21, 17), // (21,30): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // object o4 = typeof(string?); // 4, 5 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 30), // (23,32): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // object o6 = typeof(K); // 6 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(23, 32), // (24,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o7 = typeof(K?); // 7, 8 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(K?)").WithLocation(24, 17), // (24,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // object o7 = typeof(K?); // 7, 8 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(24, 31), // (25,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o8 = typeof(K?);// 9, 10, 11 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(K?)").WithLocation(25, 17), // (25,32): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // object o8 = typeof(K?);// 9, 10, 11 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(25, 32), // (25,34): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // object o8 = typeof(K?);// 9, 10, 11 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(25, 34), // (32,24): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. // object o1 = typeof(T?); // 12 Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "T?").WithLocation(32, 24), // (33,17): error CS8639: The typeof operator cannot be used on a nullable reference type // object o2 = typeof(TClass?); // 13 Diagnostic(ErrorCode.ERR_BadNullableTypeof, "typeof(TClass?)").WithLocation(33, 17)); } [Fact, WorkItem(34299, "https://github.com/dotnet/roslyn/issues/34299")] public void CheckLambdaInArrayInitializer_01() { var source = @"using System; class C { static void G(object? o, string s) { Func f = () => o; // 1 _ = f /*T:System.Func!*/; var fa3 = new[] { f, () => o, // 2 () => { s = null; // 3 return null; // 4 }, }; _ = fa3 /*T:System.Func![]!*/; fa3[0]().ToString(); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (7,32): warning CS8603: Possible null reference return. // Func f = () => o; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(7, 32), // (11,19): warning CS8603: Possible null reference return. // () => o, // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(11, 19), // (13,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 3 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 25), // (14,28): warning CS8603: Possible null reference return. // return null; // 4 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(14, 28)); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/35302"), WorkItem(35302, "https://github.com/dotnet/roslyn/issues/35302")] public void CheckLambdaInArrayInitializer_02() { var source = @"using System; class C { static void G(object? o, string s) { if (o == null) return; var f = M(o); _ = f /*T:System.Func!*/; var fa3 = new[] { f, () => null, // 1 () => { s = null; // 2 return null; // 3 }, }; _ = fa3 /*T:System.Func![]!*/; fa3[0]().ToString(); } static Func M(T t) => () => t; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (12,19): warning CS8603: Possible null reference return. // () => null, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(12, 19), // (14,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 25), // (15,28): warning CS8603: Possible null reference return. // return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(15, 28)); } [Fact, WorkItem(34299, "https://github.com/dotnet/roslyn/issues/34299")] public void CheckLambdaInSwitchExpression_01() { var source = @"using System; class C { static void G(int i, object? o, string s) { Func f = () => i; _ = f /*T:System.Func!*/; var f2 = i switch { 1 => f, 2 => () => o, // 1 _ => () => { s = null; // 2 return null; // 3 }, }; _ = f2 /*T:System.Func!*/; f2().ToString(); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( // (11,24): warning CS8603: Possible null reference return. // 2 => () => o, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(11, 24), // (11,24): warning CS8603: Possible null reference return. // 2 => () => o, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(11, 24), // (13,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 25), // (13,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 25), // (14,28): warning CS8603: Possible null reference return. // return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(14, 28), // (14,28): warning CS8603: Possible null reference return. // return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(14, 28)); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/35302"), WorkItem(34299, "https://github.com/dotnet/roslyn/issues/34299")] public void CheckLambdaInSwitchExpression_02() { var source = @"using System; class C { static void G(int i, object? o, string s) { if (o == null) return; var f = M(o); _ = f /*T:System.Func!*/; var f2 = i switch { 1 => f, 2 => () => o, // 1 _ => () => { s = null; // 2 return null; // 3 }, }; _ = f2 /*T:System.Func!*/; f2().ToString(); } static Func M(T t) => () => t; } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); //comp.VerifyTypes(); comp.VerifyDiagnostics( // (12,24): warning CS8603: Possible null reference return. // 2 => () => o, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(12, 24), // (12,24): warning CS8603: Possible null reference return. // 2 => () => o, // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "o").WithLocation(12, 24), // (14,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 25), // (14,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // s = null; // 2 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 25), // (15,28): warning CS8603: Possible null reference return. // return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(15, 28), // (15,28): warning CS8603: Possible null reference return. // return null; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "null").WithLocation(15, 28)); } [Fact, WorkItem(34299, "https://github.com/dotnet/roslyn/issues/34299")] public void CheckLambdaInLambdaInference() { var source = @"using System; class C { static Func M(Func f) => f; static void G(int i, object? o, string? s) { if (o == null) return; var f = M(() => o); var f2 = M(() => { if (i == 1) return f; if (i == 2) return () => s; // 1 return () => { return s; // 2 }; }); f2().ToString(); } } "; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,42): warning CS8603: Possible null reference return. // if (i == 2) return () => s; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(12, 42), // (14,32): warning CS8603: Possible null reference return. // return s; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(14, 32)); } [Fact, WorkItem(29956, "https://github.com/dotnet/roslyn/issues/29956")] public void ConditionalExpression_InferredResultType() { CSharpCompilation c = CreateNullableCompilation(@" class C { void Test1(object? x) { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:object?*/; if (x == null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:object?*/; } void Test2(T x) { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:void*/; if (x == null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:void*/; } void Test3(int x) { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:int?*/; if (x == null) return; // 1 M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:int?*/; } void Test4(int? x) { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:int?*/; if (x == null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:int?*/; } void Test5(T? x) where T : class { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; if (x == null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; } void Test6(T x) where T : struct { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; if (x == null) return; // 2 M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; } void Test7(T? x) where T : struct { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; if (x == null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; } void Test8(T x) where T : class { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; if (x == null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; } void Test9(T x) where T : class { M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; if (x != null) return; M(x)?.Self()/*T:Box?*/; M(x)?.Value()/*T:T?*/; } static Box M(T t) => new Box(t); } class Box { public Box Self() => this; public T Value() => throw null!; public Box(T value) { } } "); c.VerifyTypes(); c.VerifyDiagnostics( // (26,13): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' // if (x == null) return; // 1 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "x == null").WithArguments("false", "int", "int?").WithLocation(26, 13), // (53,13): error CS0019: Operator '==' cannot be applied to operands of type 'T' and '' // if (x == null) return; // 2 Diagnostic(ErrorCode.ERR_BadBinaryOps, "x == null").WithArguments("==", "T", "").WithLocation(53, 13)); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_01() { var source = @"#nullable enable using System; public class Program { static void Main(string? value) { int count = 84; if (value?.Length == count) { Console.WriteLine(value.Length); } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_02() { var source = @"#nullable enable using System; public class Program { static void Main(string? value) { if (value?.Length == (int?) null) { Console.WriteLine(value.Length); // 1 } else { Console.WriteLine(value.Length); } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(value.Length); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "value").WithLocation(10, 31)); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_03() { var source = @"#nullable enable using System; public class Program { static void Main(string? value) { int? i = null; if (value?.Length == i) { Console.WriteLine(value.Length); // 1 } else { Console.WriteLine(value.Length); // 2 } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (11,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(value.Length); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "value").WithLocation(11, 31), // (15,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(value.Length); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "value").WithLocation(15, 31)); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_04() { var source = @"#nullable enable using System; public class C { public string? s; } public class Program { static void Main(C? value) { const object? i = null; if (value?.s == i) { Console.WriteLine(value.s); // 1 } else { Console.WriteLine(value.s); } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (16,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(value.s); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "value").WithLocation(16, 31)); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_05() { var source = @"#nullable enable using System; public class Program { static void Main(string? x, string? y) { if (x?.Length == 2 && y?.Length == 2) { Console.WriteLine(x.Length); Console.WriteLine(y.Length); } else { Console.WriteLine(x.Length); // 1 Console.WriteLine(y.Length); // 2 } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (15,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(x.Length); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(15, 31), // (16,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(y.Length); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(16, 31)); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_06() { var source = @"#nullable enable using System; public class Program { static void Main(string? x, string? y) { if (x?.Length != 2 || y?.Length != 2) { Console.WriteLine(x.Length); // 1 Console.WriteLine(y.Length); // 2 } else { Console.WriteLine(x.Length); Console.WriteLine(y.Length); } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(x.Length); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 31), // (11,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(y.Length); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(11, 31)); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_07() { var source = @"#nullable enable using System; public class Program { static void Main(string? x, string? y) { if (x?.Length == 2 ? y?.Length == 2 : y?.Length == 3) { Console.WriteLine(x.Length); // 1 Console.WriteLine(y.Length); // 2 } else { Console.WriteLine(x.Length); // 3 Console.WriteLine(y.Length); // 4 } } }"; // The first warning produced for y.Length is unexpected. // https://github.com/dotnet/roslyn/issues/36096 var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (10,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(x.Length); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 31), // (11,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(y.Length); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(11, 31), // (15,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(x.Length); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(15, 31), // (16,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(y.Length); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(16, 31) ); } [Fact, WorkItem(34942, "https://github.com/dotnet/roslyn/issues/34942")] public void ConditionalAccess_08() { var source = @"#nullable enable using System; public class A { public static explicit operator B(A? a) => new B(); } public class B { } public class Program { static void Main(A? a) { B b = new B(); if ((B)a == b) { Console.WriteLine(a.ToString()); // 1 } } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (19,31): warning CS8602: Dereference of a possibly null reference. // Console.WriteLine(a.ToString()); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(19, 31)); } [Fact, WorkItem(35075, "https://github.com/dotnet/roslyn/issues/35075")] public void ConditionalExpression_TypeParameterConstrainedToNullableValueType() { CSharpCompilation c = CreateNullableCompilation(@" class C { public virtual void M(B x, U y) where U : T { } } class B : C { public override void M(B x, U y) { var z = x?.Test(y)/*T:U?*/; z = null; } T Test(T x) => throw null!; }"); c.VerifyTypes(); // Per https://github.com/dotnet/roslyn/issues/35075 errors should be expected c.VerifyDiagnostics(); } [Fact] public void AttributeAnnotation_AssertsTrue() { var source = @"#pragma warning disable 169 using System.Diagnostics.CodeAnalysis; class A : System.Attribute { internal A(object x, object y) { } } [A(Assert(F != null), F)] class Program { static object? F; static object Assert([AssertsTrue]bool b) => throw null!; }"; var comp = CreateCompilation(new[] { AssertsTrueAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,4): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(Assert(F != null), F)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "Assert(F != null)").WithLocation(7, 4), // (7,23): warning CS8604: Possible null reference argument for parameter 'y' in 'A.A(object x, object y)'. // [A(Assert(F != null), F)] Diagnostic(ErrorCode.WRN_NullReferenceArgument, "F").WithArguments("y", "A.A(object x, object y)").WithLocation(7, 23), // (7,23): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(Assert(F != null), F)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "F").WithLocation(7, 23)); } [Fact] public void AttributeAnnotation_NotNull() { var source = @"#pragma warning disable 169 using System.Diagnostics.CodeAnalysis; class A : System.Attribute { internal A(object x, object y) { } } [A(NotNull(F), F)] class Program { static object? F; static object NotNull([NotNull]object? o) => throw null!; }"; var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (7,4): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(NotNull(F), F)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "NotNull(F)").WithLocation(7, 4), // (7,16): warning CS8604: Possible null reference argument for parameter 'y' in 'A.A(object x, object y)'. // [A(NotNull(F), F)] Diagnostic(ErrorCode.WRN_NullReferenceArgument, "F").WithArguments("y", "A.A(object x, object y)").WithLocation(7, 16), // (7,16): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(NotNull(F), F)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "F").WithLocation(7, 16)); } [Fact] [WorkItem(35056, "https://github.com/dotnet/roslyn/issues/35056")] public void CircularAttribute() { var source = @"class A : System.Attribute { A([A(1)]int x) { } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } [Fact, WorkItem(34827, "https://github.com/dotnet/roslyn/issues/34827")] public void ArrayConversionToInterface() { string source = @" using System.Collections.Generic; class C { void M() { IEnumerable x1 = new[] { ""string"", null }; // 1 IEnumerable x2 = new[] { ""string"", null }; IEnumerable x3 = new[] { ""string"" }; IList x4 = new[] { ""string"", null }; // 2 ICollection x5 = new[] { ""string"", null }; ICollection x6 = new[] { ""string"" }; IReadOnlyList x7 = new[] { ""string"" }; } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics( // (7,34): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'IEnumerable'. // IEnumerable x1 = new[] { "string", null }; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, @"new[] { ""string"", null }").WithArguments("string?[]", "System.Collections.Generic.IEnumerable").WithLocation(7, 34), // (10,28): warning CS8619: Nullability of reference types in value of type 'string?[]' doesn't match target type 'IList'. // IList x4 = new[] { "string", null }; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, @"new[] { ""string"", null }").WithArguments("string?[]", "System.Collections.Generic.IList").WithLocation(10, 28) ); } [Fact, WorkItem(34827, "https://github.com/dotnet/roslyn/issues/34827")] public void ArrayConversionToInterface_Nested() { string source = @" using System.Collections.Generic; class C { void M() { IEnumerable x1 = new[] { new[] { ""string"", null } }; // 1 IEnumerable x2 = new[] { new[] { ""string"", null } }; // 2 IEnumerable x3 = new[] { new[] { ""string"", null } }; IEnumerable x4 = new[] { new[] { ""string"" } }; IEnumerable> x5 = new[] { new[] { ""string"" , null } }; // 3 IEnumerable> x6 = new[] { new[] { ""string"" , null } }; IEnumerable> x7 = new[] { new[] { ""string"" } }; } }"; var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics( // (7,36): warning CS8619: Nullability of reference types in value of type 'string?[][]' doesn't match target type 'IEnumerable'. // IEnumerable x1 = new[] { new[] { "string", null } }; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, @"new[] { new[] { ""string"", null } }").WithArguments("string?[][]", "System.Collections.Generic.IEnumerable").WithLocation(7, 36), // (8,37): warning CS8619: Nullability of reference types in value of type 'string?[][]' doesn't match target type 'IEnumerable'. // IEnumerable x2 = new[] { new[] { "string", null } }; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, @"new[] { new[] { ""string"", null } }").WithArguments("string?[][]", "System.Collections.Generic.IEnumerable").WithLocation(8, 37), // (11,47): warning CS8619: Nullability of reference types in value of type 'string?[][]' doesn't match target type 'IEnumerable>'. // IEnumerable> x5 = new[] { new[] { "string" , null } }; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, @"new[] { new[] { ""string"" , null } }").WithArguments("string?[][]", "System.Collections.Generic.IEnumerable>").WithLocation(11, 47) ); } [Fact] [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] public void ExtensionMethodDelegate_01() { var source = @"delegate void D0(); delegate void D1(T t); static class E { internal static void F(this T t) { } } class Program { static void M0(string? x, string y) { D0 d; d = x.F; d = x.F; d = x.F; // 1 d = y.F; d = y.F; d = y.F; } static void M1() { D1 d; D1 e; d = E.F; d = E.F; // 2 e = E.F; e = E.F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t)'. // d = x.F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t)").WithLocation(14, 13), // (24,13): warning CS8622: Nullability of reference types in type of parameter 't' of 'void E.F(string t)' doesn't match the target delegate 'D1'. // d = E.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "E.F").WithArguments("t", "void E.F(string t)", "D1").WithLocation(24, 13)); } [Fact] public void ExtensionMethodDelegate_02() { var source = @"delegate void D0(); delegate void D1(T t); static class E { internal static void F(this T t) { } } class Program { static void M0(string? x, string y) { _ = new D0(x.F); _ = new D0(x.F); _ = new D0(x.F); // 1 _ = new D0(y.F); _ = new D0(y.F); _ = new D0(y.F); } static void M1() { _ = new D1(E.F); _ = new D1(E.F); // 2 _ = new D1(E.F); _ = new D1(E.F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,20): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t)'. // _ = new D0(x.F); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t)").WithLocation(13, 20), // (21,29): warning CS8622: Nullability of reference types in type of parameter 't' of 'void E.F(string t)' doesn't match the target delegate 'D1'. // _ = new D1(E.F); // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "E.F").WithArguments("t", "void E.F(string t)", "D1").WithLocation(21, 29)); } [Fact] [WorkItem(30287, "https://github.com/dotnet/roslyn/issues/30287")] [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] public void ExtensionMethodDelegate_03() { var source = @"delegate void D(T t); static class E { internal static void F(this T t, int i) { } } class Program { static void M(string? x, string y) { D d; d = x.F; d = x.F; d = x.F; // 1 d = y.F; d = y.F; d = y.F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, int i)'. // d = x.F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, int i)").WithLocation(13, 13)); } [Fact] [WorkItem(30287, "https://github.com/dotnet/roslyn/issues/30287")] public void ExtensionMethodDelegate_04() { var source = @"delegate void D(T t); static class E { internal static void F(this T t, int i) { } } class Program { static void M(string? x, string y) { _ = new D(x.F); _ = new D(x.F); _ = new D(x.F); // 1 _ = new D(y.F); _ = new D(y.F); _ = new D(y.F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,24): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, int i)'. // _ = new D(x.F); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, int i)").WithLocation(12, 24)); } [Fact] [WorkItem(30287, "https://github.com/dotnet/roslyn/issues/30287")] [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] public void ExtensionMethodDelegate_05() { var source = @"delegate void D(T t); static class E { internal static void F(this T t, U u) { } } class Program { static void M(string? x, string y) { D d; D e; d = x.F; e = x.F; d = x.F; // 1 e = x.F; // 2 d = y.F; e = y.F; d = y.F; e = y.F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (14,13): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string? u)'. // d = x.F; // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string? u)").WithLocation(14, 13), // (15,13): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string u)'. // e = x.F; // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string u)").WithLocation(15, 13)); } [Fact] [WorkItem(30287, "https://github.com/dotnet/roslyn/issues/30287")] public void ExtensionMethodDelegate_06() { var source = @"delegate void D(T t); static class E { internal static void F(this T t, U u) { } } class Program { static void M(string? x, string y) { _ = new D(x.F); _ = new D(x.F); _ = new D(x.F); // 1 _ = new D(x.F); // 2 _ = new D(y.F); _ = new D(y.F); _ = new D(y.F); _ = new D(y.F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,28): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string? u)'. // _ = new D(x.F); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string? u)").WithLocation(12, 28), // (13,27): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string u)'. // _ = new D(x.F); // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string u)").WithLocation(13, 27)); } [Fact] [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] public void ExtensionMethodDelegate_07() { var source = @"delegate void D(); static class E { internal static void F(this T t) { } } class Program { static void M() where U : class where V : struct { D d; d = default(T).F; d = default(U).F; d = default(V).F; d = default(V?).F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,13): error CS1113: Extension method 'E.F(T)' defined on value type 'T' cannot be used to create delegates // d = default(T).F; Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "default(T).F").WithArguments("E.F(T)", "T").WithLocation(13, 13), // (13,13): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // d = default(T).F; Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(13, 13), // (15,13): error CS1113: Extension method 'E.F(V)' defined on value type 'V' cannot be used to create delegates // d = default(V).F; Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "default(V).F").WithArguments("E.F(V)", "V").WithLocation(15, 13), // (16,13): error CS1113: Extension method 'E.F(V?)' defined on value type 'V?' cannot be used to create delegates // d = default(V?).F; Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "default(V?).F").WithArguments("E.F(V?)", "V?").WithLocation(16, 13)); } [Fact] [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] public void ExtensionMethodDelegate_08() { var source = @"delegate void D(); static class E { internal static void F(this T t) { } } class Program { static void M() where U : class where V : struct { _ = new D(default(T).F); _ = new D(default(U).F); _ = new D(default(V).F); _ = new D(default(V?).F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,19): error CS1113: Extension method 'E.F(T)' defined on value type 'T' cannot be used to create delegates // _ = new D(default(T).F); Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "default(T).F").WithArguments("E.F(T)", "T").WithLocation(12, 19), // (12,19): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type. // _ = new D(default(T).F); Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T)").WithArguments("T").WithLocation(12, 19), // (14,19): error CS1113: Extension method 'E.F(V)' defined on value type 'V' cannot be used to create delegates // _ = new D(default(V).F); Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "default(V).F").WithArguments("E.F(V)", "V").WithLocation(14, 19), // (15,19): error CS1113: Extension method 'E.F(V?)' defined on value type 'V?' cannot be used to create delegates // _ = new D(default(V?).F); Diagnostic(ErrorCode.ERR_ValueTypeExtDelegate, "default(V?).F").WithArguments("E.F(V?)", "V?").WithLocation(15, 19)); } [Fact] [WorkItem(30563, "https://github.com/dotnet/roslyn/issues/30563")] public void ExtensionMethodDelegate_09() { var source = @"delegate T D(); static class E { internal static T F(this T t) => t; } class Program { static void M() where T : class { T? t = default; D d; d = t.F; // 1 d = t.F!; d = t.F; // 2 d = t.F!; _ = new D(t.F); // 3 _ = new D(t.F!); _ = new D(t.F); // 4 _ = new D(t.F!); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,13): warning CS8621: Nullability of reference types in return type of 'T? E.F(T? t)' doesn't match the target delegate 'D'. // d = t.F; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "t.F").WithArguments("T? E.F(T? t)", "D").WithLocation(12, 13), // (14,13): warning CS8621: Nullability of reference types in return type of 'T? E.F(T? t)' doesn't match the target delegate 'D'. // d = t.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "t.F").WithArguments("T? E.F(T? t)", "D").WithLocation(14, 13), // (16,22): warning CS8621: Nullability of reference types in return type of 'T? E.F(T? t)' doesn't match the target delegate 'D'. // _ = new D(t.F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "t.F").WithArguments("T? E.F(T? t)", "D").WithLocation(16, 22), // (18,22): warning CS8621: Nullability of reference types in return type of 'T? E.F(T? t)' doesn't match the target delegate 'D'. // _ = new D(t.F); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "t.F").WithArguments("T? E.F(T? t)", "D").WithLocation(18, 22)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void DelegateInferredNullability_01() { var source = @"delegate T D(); class C { internal T F() => throw null!; } class Program { static C Create(T t) => new C(); static void M() { object? x = new object(); object y = null; // 1 D d1; D d2; d1 = Create(x).F; d2 = Create(x).F; d1 = Create(y).F; d2 = Create(y).F; // 2 _ = new D(Create(x).F); _ = new D(Create(x).F); _ = new D(Create(y).F); _ = new D(Create(y).F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 20), // (18,14): warning CS8621: Nullability of reference types in return type of 'object? C.F()' doesn't match the target delegate 'D'. // d2 = Create(y).F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "Create(y).F").WithArguments("object? C.F()", "D").WithLocation(18, 14), // (22,27): warning CS8621: Nullability of reference types in return type of 'object? C.F()' doesn't match the target delegate 'D'. // _ = new D(Create(y).F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "Create(y).F").WithArguments("object? C.F()", "D").WithLocation(22, 27)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void DelegateInferredNullability_02() { var source = @"delegate void D(T t); class C { internal void F(T t) { } } class Program { static C Create(T t) => new C(); static void M() { object? x = new object(); object y = null; // 1 D d1; D d2; d1 = Create(x).F; // 2 d2 = Create(x).F; d1 = Create(y).F; d2 = Create(y).F; _ = new D(Create(x).F); // 3 _ = new D(Create(x).F); _ = new D(Create(y).F); _ = new D(Create(y).F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 20), // (15,14): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(object t)' doesn't match the target delegate 'D'. // d1 = Create(x).F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "Create(x).F").WithArguments("t", "void C.F(object t)", "D").WithLocation(15, 14), // (19,28): warning CS8622: Nullability of reference types in type of parameter 't' of 'void C.F(object t)' doesn't match the target delegate 'D'. // _ = new D(Create(x).F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate, "Create(x).F").WithArguments("t", "void C.F(object t)", "D").WithLocation(19, 28)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void DelegateInferredNullability_03() { var source = @"delegate T D(); class C { internal U F() where U : T => throw null!; } class Program { static C Create(T t) => new C(); static void M() where T : class, new() { T? x = new T(); T y = null; // 1 D d1; D d2; d1 = Create(x).F; // 2 d2 = Create(x).F; d1 = Create(y).F; d2 = Create(y).F; _ = new D(Create(x).F); // 3 _ = new D(Create(x).F); _ = new D(Create(y).F); _ = new D(Create(y).F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 15), // (15,14): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'C.F()'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // d1 = Create(x).F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Create(x).F").WithArguments("C.F()", "T", "U", "T?").WithLocation(15, 14), // (19,23): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'C.F()'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // _ = new D(Create(x).F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Create(x).F").WithArguments("C.F()", "T", "U", "T?").WithLocation(19, 23)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void DelegateInferredNullability_04() { var source = @"delegate void D(T t); class C { internal void F(U u) where U : T { } } class Program { static C Create(T t) => new C(); static void M() where T : class, new() { T? x = new T(); T y = null; // 1 D d1; D d2; d1 = Create(x).F; // 2 d2 = Create(x).F; d1 = Create(y).F; d2 = Create(y).F; _ = new D(Create(x).F); // 3 _ = new D(Create(x).F); _ = new D(Create(y).F); _ = new D(Create(y).F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 15), // (15,14): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'C.F(U)'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // d1 = Create(x).F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Create(x).F").WithArguments("C.F(U)", "T", "U", "T?").WithLocation(15, 14), // (19,23): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'C.F(U)'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // _ = new D(Create(x).F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Create(x).F").WithArguments("C.F(U)", "T", "U", "T?").WithLocation(19, 23)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void DelegateInferredNullability_05() { var source = @"delegate void D(T t); class C { internal void F(U u) where U : T { } } class Program { static C Create(T t) => new C(); static void M() where T : class, new() { T? x = new T(); T y = null; // 1 D d1; D d2; d1 = Create(x).F; // 2 d2 = Create(x).F; d1 = Create(y).F; d2 = Create(y).F; _ = new D(Create(x).F); // 3 _ = new D(Create(x).F); _ = new D(Create(y).F); _ = new D(Create(y).F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (12,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(12, 15), // (15,14): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'C.F(U)'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // d1 = Create(x).F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Create(x).F").WithArguments("C.F(U)", "T", "U", "T?").WithLocation(15, 14), // (19,23): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'C.F(U)'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // _ = new D(Create(x).F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Create(x).F").WithArguments("C.F(U)", "T", "U", "T?").WithLocation(19, 23)); } [Fact] [WorkItem(35274, "https://github.com/dotnet/roslyn/issues/35274")] public void DelegateInferredNullability_06() { var source = @"delegate T D(); class C { internal T F() => throw null!; } class Program { static C Create(T t) => new C(); static void Main() { string? s = null; var x = Create(s); C y = Create(s); D d; d = Create(s).F; // 1 d = x.F; // 2 d = y.F; // 3 _ = new D(Create(s).F); // 4 _ = new D(x.F); // 5 _ = new D(y.F); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (15,13): warning CS8621: Nullability of reference types in return type of 'string? C.F()' doesn't match the target delegate 'D'. // d = Create(s).F; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "Create(s).F").WithArguments("string? C.F()", "D").WithLocation(15, 13), // (16,13): warning CS8621: Nullability of reference types in return type of 'string? C.F()' doesn't match the target delegate 'D'. // d = x.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.F").WithArguments("string? C.F()", "D").WithLocation(16, 13), // (17,13): warning CS8621: Nullability of reference types in return type of 'string? C.F()' doesn't match the target delegate 'D'. // d = y.F; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "y.F").WithArguments("string? C.F()", "D").WithLocation(17, 13), // (18,27): warning CS8621: Nullability of reference types in return type of 'string? C.F()' doesn't match the target delegate 'D'. // _ = new D(Create(s).F); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "Create(s).F").WithArguments("string? C.F()", "D").WithLocation(18, 27), // (19,27): warning CS8621: Nullability of reference types in return type of 'string? C.F()' doesn't match the target delegate 'D'. // _ = new D(x.F); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.F").WithArguments("string? C.F()", "D").WithLocation(19, 27), // (20,27): warning CS8621: Nullability of reference types in return type of 'string? C.F()' doesn't match the target delegate 'D'. // _ = new D(y.F); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "y.F").WithArguments("string? C.F()", "D").WithLocation(20, 27)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_01() { var source = @"delegate T D(); static class E { internal static T F(this T t) => t; } class Program { static void M() { object? x = new object(); object y = null; // 1 D d1; D d2; d1 = x.F; d2 = x.F; d1 = y.F; d2 = y.F; // 2 _ = new D(x.F); _ = new D(x.F); _ = new D(y.F); _ = new D(y.F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 20), // (17,14): warning CS8621: Nullability of reference types in return type of 'object? E.F(object? t)' doesn't match the target delegate 'D'. // d2 = y.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "y.F").WithArguments("object? E.F(object? t)", "D").WithLocation(17, 14), // (21,27): warning CS8621: Nullability of reference types in return type of 'object? E.F(object? t)' doesn't match the target delegate 'D'. // _ = new D(y.F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "y.F").WithArguments("object? E.F(object? t)", "D").WithLocation(21, 27)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_02() { var source = @"delegate void D(T t); static class E { internal static void F(this T x, T y) { } } class Program { static void M() { object? x = new object(); object y = null; // 1 D d1; D d2; d1 = x.F; d2 = x.F; d1 = y.F; d2 = y.F; _ = new D(x.F); _ = new D(x.F); _ = new D(y.F); _ = new D(y.F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 20)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_03() { var source = @"delegate void D(T t); static class E { internal static void F(this T x, T y) { } } class Program { static void M() { object? x = new object(); object y = null; // 1 D d1; D d2; d1 = x.F; d2 = x.F; d1 = y.F; d2 = y.F; // 2 _ = new D(x.F); _ = new D(x.F); _ = new D(y.F); _ = new D(y.F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 20), // (17,14): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(object x, object y)'. // d2 = y.F; // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(object x, object y)").WithLocation(17, 14), // (21,27): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(object x, object y)'. // _ = new D(y.F); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(object x, object y)").WithLocation(21, 27)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_04() { var source = @"delegate T D(); static class E { internal static T F(this T t) => t; } class Program { static void M() where T : class, new() { T? x = new T(); T y = null; // 1 D d1; D d2; d1 = x.F; d2 = x.F; d1 = y.F; d2 = y.F; // 2 _ = new D(x.F); _ = new D(x.F); _ = new D(y.F); _ = new D(y.F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 15), // (17,14): warning CS8604: Possible null reference argument for parameter 't' in 'T E.F(T t)'. // d2 = y.F; // 2 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "T E.F(T t)").WithLocation(17, 14), // (21,22): warning CS8604: Possible null reference argument for parameter 't' in 'T E.F(T t)'. // _ = new D(y.F); // 3 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "T E.F(T t)").WithLocation(21, 22)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_05() { var source = @"delegate void D(T t); static class E { internal static void F(this T t, U u) where U : T { } } class Program { static void M() where T : class, new() { T? x = new T(); T y = null; // 1 D d1; D d2; d1 = x.F; // 2 d2 = x.F; d1 = y.F; d2 = y.F; _ = new D(x.F); // 3 _ = new D(x.F); _ = new D(y.F); _ = new D(y.F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 15), // (14,14): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'E.F(T, U)'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // d1 = x.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "x.F").WithArguments("E.F(T, U)", "T", "U", "T?").WithLocation(14, 14), // (18,23): warning CS8631: The type 'T?' cannot be used as type parameter 'U' in the generic type or method 'E.F(T, U)'. Nullability of type argument 'T?' doesn't match constraint type 'T'. // _ = new D(x.F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "x.F").WithArguments("E.F(T, U)", "T", "U", "T?").WithLocation(18, 23)); } [Fact] [WorkItem(35274, "https://github.com/dotnet/roslyn/issues/35274")] public void ExtensionMethodDelegateInferredNullability_06() { var source = @"delegate T D(); class C { } static class E { internal static T F(this C c) => throw null!; } class Program { static C Create(T t) => new C(); static void Main() { string? s = null; var x = Create(s); C y = Create(s); D d; d = Create(s).F; // 1 d = x.F; // 2 d = y.F; // 3 _ = new D(Create(s).F); // 4 _ = new D(x.F); // 5 _ = new D(y.F); // 6 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (18,13): warning CS8621: Nullability of reference types in return type of 'string? E.F(C c)' doesn't match the target delegate 'D'. // d = Create(s).F; // 1 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "Create(s).F").WithArguments("string? E.F(C c)", "D").WithLocation(18, 13), // (19,13): warning CS8621: Nullability of reference types in return type of 'string? E.F(C c)' doesn't match the target delegate 'D'. // d = x.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.F").WithArguments("string? E.F(C c)", "D").WithLocation(19, 13), // (20,13): warning CS8621: Nullability of reference types in return type of 'string? E.F(C c)' doesn't match the target delegate 'D'. // d = y.F; // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "y.F").WithArguments("string? E.F(C c)", "D").WithLocation(20, 13), // (21,27): warning CS8621: Nullability of reference types in return type of 'string? E.F(C c)' doesn't match the target delegate 'D'. // _ = new D(Create(s).F); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "Create(s).F").WithArguments("string? E.F(C c)", "D").WithLocation(21, 27), // (22,27): warning CS8621: Nullability of reference types in return type of 'string? E.F(C c)' doesn't match the target delegate 'D'. // _ = new D(x.F); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.F").WithArguments("string? E.F(C c)", "D").WithLocation(22, 27), // (23,27): warning CS8621: Nullability of reference types in return type of 'string? E.F(C c)' doesn't match the target delegate 'D'. // _ = new D(y.F); // 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "y.F").WithArguments("string? E.F(C c)", "D").WithLocation(23, 27)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_07() { var source = @"delegate T D(); static class E { internal static T F(this T t) where T : class => t; } class Program { static void M() where T : class, new() { T? x = new T(); T y = null; // 1 D d; d = x.F; d = y.F; // 2 _ = new D(x.F); _ = new D(y.F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (11,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 15), // (14,13): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'E.F(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // d = y.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "y.F").WithArguments("E.F(T)", "T", "T?").WithLocation(14, 13), // (16,23): warning CS8634: The type 'T?' cannot be used as type parameter 'T' in the generic type or method 'E.F(T)'. Nullability of type argument 'T?' doesn't match 'class' constraint. // _ = new D(y.F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "y.F").WithArguments("E.F(T)", "T", "T?").WithLocation(16, 23)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_08() { var source = @"delegate T D(); static class E { internal static T F(this T t) => t; } class Program { static void M() where T : class, new() { T x; N(() => { x = null; // 1 D d = x.F; // 2 _ = new D(x.F); // 3 }); } static void N(System.Action a) { } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (13,17): warning CS8600: Converting null literal or possible null value to non-nullable type. // x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(13, 17), // (14,22): warning CS8621: Nullability of reference types in return type of 'T? E.F(T? t)' doesn't match the target delegate 'D'. // D d = x.F; // 2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.F").WithArguments("T? E.F(T? t)", "D").WithLocation(14, 22), // (15,26): warning CS8621: Nullability of reference types in return type of 'T? E.F(T? t)' doesn't match the target delegate 'D'. // _ = new D(x.F); // 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "x.F").WithArguments("T? E.F(T? t)", "D").WithLocation(15, 26)); } [Fact] [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] public void ExtensionMethodDelegateInferredNullability_09() { var source = @"delegate T D(); static class E { internal static T F(this T t) => t; } class A : System.Attribute { internal A(D d) { } } [A(default(string).F)] class Program { }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,2): error CS0181: Attribute constructor parameter 'd' has type 'D', which is not a valid attribute parameter type // [A(default(string).F)] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "A").WithArguments("d", "D").WithLocation(10, 2), // (10,4): warning CS8621: Nullability of reference types in return type of 'string? E.F(string? t)' doesn't match the target delegate 'D'. // [A(default(string).F)] Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate, "default(string).F").WithArguments("string? E.F(string? t)", "D").WithLocation(10, 4)); } [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_01() { var source = @"class C { public static C operator &(C a, C b) => a; } class Program { static void M(C a, string s) { var b = Create(s); _ = a & b; } static C Create(T t) => new C(); }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(); } // C operator op(C, C) [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_02() { var source = @"#nullable disable class C { public static C operator +(C a, C b) => a; } class Program { static void M1( #nullable disable C a, #nullable enable C b) { _ = a + a; _ = a + b; _ = b + a; _ = b + b; } static void M2( #nullable disable C c, #nullable enable C d) where T : class? { _ = c + c; _ = c + d; _ = d + c; _ = d + d; } static void M3( #nullable disable C x, #nullable enable C y, C z) where T : class { _ = x + x; _ = x + y; _ = x + z; _ = y + x; _ = y + y; _ = y + z; _ = z + x; _ = z + y; _ = z + z; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (44,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator +(C a, C b)' due to differences in the nullability of reference types. // _ = y + z; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator +(C a, C b)").WithLocation(44, 17), // (46,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator +(C a, C b)' due to differences in the nullability of reference types. // _ = z + y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "C", "b", "C C.operator +(C a, C b)").WithLocation(46, 17)); } // C operator op(C, C) [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_03() { var source = @"#nullable enable class C { public static C operator -(C a, C b) => a; } class Program { static void M1( #nullable disable C a, #nullable enable C b) { _ = a - a; _ = a - b; _ = b - a; _ = b - b; } static void M2( #nullable disable C c, #nullable enable C d) where T : class? { _ = c - c; _ = c - d; _ = d - c; _ = d - d; } static void M3( #nullable disable C x, #nullable enable C y, C z) where T : class { _ = x - x; _ = x - y; _ = x - z; _ = y - x; _ = y - y; _ = y - z; _ = z - x; _ = z - y; _ = z - z; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (44,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator -(C a, C b)' due to differences in the nullability of reference types. // _ = y - z; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator -(C a, C b)").WithLocation(44, 17), // (46,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator -(C a, C b)' due to differences in the nullability of reference types. // _ = z - y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "C", "b", "C C.operator -(C a, C b)").WithLocation(46, 17)); } // C operator op(C, C) [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_04() { var source = @"class C { #nullable disable public static C operator *( C a, #nullable enable C b) => a; } class Program { static void M1( #nullable disable C a, #nullable enable C b) { _ = a * a; _ = a * b; _ = b * a; _ = b * b; } static void M2( #nullable disable C c, #nullable enable C d) where T : class? { _ = c * c; _ = c * d; _ = d * c; _ = d * d; } static void M3( #nullable disable C x, #nullable enable C y, C z) where T : class { _ = x * x; _ = x * y; _ = x * z; _ = y * x; _ = y * y; _ = y * z; _ = z * x; _ = z * y; _ = z * z; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (47,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator *(C a, C b)' due to differences in the nullability of reference types. // _ = y * z; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator *(C a, C b)").WithLocation(47, 17), // (49,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator *(C a, C b)' due to differences in the nullability of reference types. // _ = z * y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "C", "b", "C C.operator *(C a, C b)").WithLocation(49, 17)); } // C operator op(C, C) where T : class? [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_05() { var source = @"#nullable enable class C where T : class? { #nullable disable public static C operator +(C a, C b) => a; } class Program { static void M1( #nullable disable C a, #nullable enable C b) where T : class? { _ = a + a; _ = a + b; _ = b + a; _ = b + b; } static void M2( #nullable disable C x, #nullable enable C y, C z) where T : class { _ = x + x; _ = x + y; _ = x + z; _ = y + x; _ = y + y; _ = y + z; _ = z + x; _ = z + y; _ = z + z; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (34,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator +(C a, C b)' due to differences in the nullability of reference types. // _ = y + z; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator +(C a, C b)").WithLocation(34, 17), // (36,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator +(C a, C b)' due to differences in the nullability of reference types. // _ = z + y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "C", "b", "C C.operator +(C a, C b)").WithLocation(36, 17)); } // C operator op(C, C) where T : class? [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_06() { var source = @"#nullable enable class C where T : class? { public static C operator -(C a, C b) => a; } class Program { static void M1( #nullable disable C a, #nullable enable C b) where T : class? { _ = a - a; _ = a - b; _ = b - a; _ = b - b; } static void M2( #nullable disable C x, #nullable enable C y, C z) where T : class { _ = x - x; _ = x - y; _ = x - z; _ = y - x; _ = y - y; _ = y - z; _ = z - x; _ = z - y; _ = z - z; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (33,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator -(C a, C b)' due to differences in the nullability of reference types. // _ = y - z; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator -(C a, C b)").WithLocation(33, 17), // (35,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator -(C a, C b)' due to differences in the nullability of reference types. // _ = z - y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "C", "b", "C C.operator -(C a, C b)").WithLocation(35, 17)); } // C operator op(C, C) where T : class? [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_07() { var source = @"#nullable enable class C where T : class? { #nullable disable public static C operator *( #nullable enable C a, #nullable disable C b) => a; } class Program { static void M1( #nullable disable C a, #nullable enable C b) where T : class? { _ = a * a; _ = a * b; _ = b * a; _ = b * b; } static void M2( #nullable disable C x, #nullable enable C y, C z) where T : class { _ = x * x; _ = x * y; _ = x * z; _ = y * x; _ = y * y; _ = y * z; _ = z * x; _ = z * y; _ = z * z; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (38,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator *(C a, C b)' due to differences in the nullability of reference types. // _ = y * z; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator *(C a, C b)").WithLocation(38, 17), // (40,17): warning CS8620: Argument of type 'C' cannot be used for parameter 'b' of type 'C' in 'C C.operator *(C a, C b)' due to differences in the nullability of reference types. // _ = z * y; Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("C", "C", "b", "C C.operator *(C a, C b)").WithLocation(40, 17)); } // C operator op(C, C) where T : class [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_08() { var source = @"#nullable enable class C where T : class { #nullable disable public static C operator /(C a, C b) => a; } class Program { static void M( #nullable disable C x, #nullable enable C y) where T : class { _ = x / x; _ = x / y; _ = y / x; _ = y / y; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } // C operator op(C, C) where T : class [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_09() { var source = @"#nullable enable class C where T : class { public static C operator &(C a, C b) => a; } class Program { static void M( #nullable disable C x, #nullable enable C y) where T : class { _ = x & x; _ = x & y; _ = y & x; _ = y & y; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } // C operator op(C, C) where T : class [Fact] [WorkItem(35057, "https://github.com/dotnet/roslyn/issues/35057")] public void Operator_10() { var source = @"#nullable enable class C where T : class { #nullable disable public static C operator |( #nullable enable C a, #nullable disable C b) => a; } class Program { static void M( #nullable disable C x, #nullable enable C y) where T : class { _ = x | x; _ = x | y; _ = y | x; _ = y | y; } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirective() { var source = @" class C { void M(object? o1) { object o2 = o1; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (6,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object o2 = o1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "o1").WithLocation(6, 21)); Assert.True(comp.ShouldRunNullableWalker); } [Theory] [InlineData("")] [InlineData("annotations")] [InlineData("warnings")] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirective_WithNullDisables(string directive) { var source = $@" #nullable disable {directive} class C {{ void M(object? o1) {{ object o2 = o1; }} }}"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics(directive == "warnings" ? DiagnosticDescription.None : new[] { // (5,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 18) }); Assert.True(comp.ShouldRunNullableWalker); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableEnable() { ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableDirective("", // (7,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object o2 = o1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "o1").WithLocation(7, 21)); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableEnableAnnotations() { ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableDirective("annotations"); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableEnableWarnings() { ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableDirective("warnings", // (5,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 18)); } private static void ShouldRunNullableWalker_GlobalDirectiveOff_WithNullableDirective(string directive, params DiagnosticDescription[] expectedDiagnostics) { var source = $@" #nullable enable {directive} class C {{ void M(object? o1) {{ object o2 = o1; }} }}"; var comp = CreateCompilation(source, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics(expectedDiagnostics); Assert.True(comp.ShouldRunNullableWalker); } [Theory] [InlineData("disable")] [InlineData("disable annotations")] [InlineData("disable warnings")] [InlineData("restore")] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_WithNonInfluencingNullableDirectives(string directive) { var source = $@" #nullable {directive} class C {{ void M(object? o1) {{ object o2 = o1; }} }}"; var comp = CreateCompilation(source, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics( // (5,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 18)); Assert.False(comp.ShouldRunNullableWalker); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles_NullableEnable() { ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles("", // (4,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 18), // (7,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object o4 = o3; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "o3").WithLocation(7, 21)); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles_NullableEnableAnnotations() { ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles("annotations", // (4,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 18)); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles_NullableEnableWarnings() { ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles("warnings", // (4,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 18), // (5,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o3) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 18)); } private static void ShouldRunNullableWalker_GlobalDirectiveOff_MultipleFiles(string directive, params DiagnosticDescription[] expectedDiagnostics) { var source1 = @" class C { void M(object? o1) { object o2 = o1; } }"; var source2 = $@" #nullable enable {directive} class D {{ void M(object? o3) {{ object o4 = o3; }} }}"; var comp = CreateCompilation(new[] { source1, source2 }, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics(expectedDiagnostics); Assert.True(comp.ShouldRunNullableWalker); } [Fact] [WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")] public void ShouldRunNullableWalker_GlobalDirectiveOff_MultipleDirectivesSingleFile() { var source = @" #nullable disable class C { void M(object? o1) { #nullable enable object o2 = o1; #nullable restore } }"; var comp = CreateCompilation(source, options: WithNonNullTypesFalse()); comp.VerifyDiagnostics( // (5,18): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // void M(object? o1) Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 18), // (8,21): warning CS8600: Converting null literal or possible null value to non-nullable type. // object o2 = o1; Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "o1").WithLocation(8, 21)); Assert.True(comp.ShouldRunNullableWalker); } } }