diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs index 1091ee6000a1..279bf5e3600c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs @@ -1148,6 +1148,10 @@ private static void MergeHidingLookupResults(LookupResult resultHiding, LookupRe // SPEC: interface type, the base types of T are the base interfaces // SPEC: of T and the class type object. + if (hiddenContainer.Equals(hidingSym.ContainingType, TypeCompareKind.IgnoreNullableModifiersForReferenceTypes)) + { + goto symIsHidden; // discard the new candidate, as it is not really different + } if (!IsDerivedType(baseType: hiddenContainer, derivedType: hidingSym.ContainingType, basesBeingResolved, useSiteDiagnostics: ref useSiteDiagnostics) && hiddenContainer.SpecialType != SpecialType.System_Object) { diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index ffa2eeb78e85..1c8320d2f875 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -3828,7 +3828,7 @@ void splitAndLearnFromNonNullTest(BoundExpression operandComparedToNonNull, bool } derivedType = derivedType.StrippedType(); HashSet? useSiteDiagnostics = null; - var conversion = _conversions.ClassifyBuiltInConversion(derivedType, baseType, ref useSiteDiagnostics); + var conversion = _conversions.WithNullability(false).ClassifyBuiltInConversion(derivedType, baseType, ref useSiteDiagnostics); if (conversion.Exists && !conversion.IsExplicit) { return derivedType; diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 1e97e109ba08..90f0fb17b763 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -877,7 +877,8 @@ private TypeSymbol MergeTupleNames(NamedTypeSymbol other, NamedTypeSymbol merged } } - bool namesUnchanged = mergedNames.IsDefault ? TupleElementNames.IsDefault : mergedNames.SequenceEqual(TupleElementNames); + // TODO2 bug number + bool namesUnchanged = mergedNames.IsDefault ? TupleElementNames.IsDefault : mergedNames.SequenceEqual(TupleElementNames, comparer: null); return (namesUnchanged && this.Equals(mergedType, TypeCompareKind.ConsiderEverything)) ? this : CreateTuple(mergedType, mergedNames, this.TupleErrorPositions, this.TupleElementLocations, this.Locations); diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs index e7796d6cabd6..197757467fe4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs @@ -475,30 +475,19 @@ internal TypeWithAnnotations SubstituteTypeCore(AbstractTypeMap typeMap) { newAnnotation = NullableAnnotation.Annotated; } - else if (IsIndexedTypeParameter(newTypeWithModifiers.Type)) + else if (NullableAnnotation.IsNotAnnotated()) { - newAnnotation = NullableAnnotation; + newAnnotation = NullableAnnotation.NotAnnotated; } - else if (NullableAnnotation != NullableAnnotation.Oblivious) + else if (newTypeWithModifiers.NullableAnnotation.IsNotAnnotated()) { - if (!typeSymbol.IsTypeParameterDisallowingAnnotationInCSharp8()) - { - newAnnotation = NullableAnnotation; - } - else - { - newAnnotation = newTypeWithModifiers.NullableAnnotation; - } - } - else if (newTypeWithModifiers.NullableAnnotation != NullableAnnotation.Oblivious) - { - newAnnotation = newTypeWithModifiers.NullableAnnotation; + newAnnotation = NullableAnnotation.NotAnnotated; } else { Debug.Assert(NullableAnnotation.IsOblivious()); Debug.Assert(newTypeWithModifiers.NullableAnnotation.IsOblivious()); - newAnnotation = NullableAnnotation; + newAnnotation = NullableAnnotation.Oblivious; } return CreateNonLazyType( diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Nullable.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Nullable.cs index 4c00bad5f44b..7247c4d85fbb 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Nullable.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Nullable.cs @@ -72,7 +72,7 @@ public interface I0 : I1 imc1.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( - new[] { "I1", "I2" }, + new[] { "I1", "I2" }, imc1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); var client_source = @" @@ -90,12 +90,12 @@ public void M(I0 imc) // Note: it is expected that the symbol shows different Interfaces in PE vs. compilation reference AssertEx.SetEqual( useImageReferences - ? new[] { "I1", "I2" } + ? new[] { "I1", "I2" } : new[] { "I1" }, imc2.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( - new[] { "I1", "I2" }, + new[] { "I1", "I2" }, imc2.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); } @@ -136,7 +136,7 @@ public class C0 : I1 lib2_c0.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( - new[] { "I1", "I2" }, + new[] { "I1", "I2" }, lib2_c0.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); CompileAndVerify(lib2_comp, validator: assembly => @@ -171,7 +171,7 @@ public class C1 : C0 lib3_c0.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( - new[] { "I1", "I2" }, + new[] { "I1", "I2" }, lib3_c0.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); CompileAndVerify(lib3_comp, validator: assembly => diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 3aa77e69f5f7..2e5defa502d4 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -9718,22 +9718,22 @@ public void M() { Oblivious.s.Item /*T:string!*/ = null; - External.s.Item /*T:string!*/ = null; // warn 1 + External.s.Item /*T:string!*/ = null; // 1 External.ns.Item /*T:string?*/ = null; - External.fs.Item /*T:string!*/ = null; + External.fs.Item /*T:string!*/ = null; // 2 External.fns.Item /*T:string?*/ = null; - OuterA.A.s.Item /*T:string!*/ = null; // warn 2 + OuterA.A.s.Item /*T:string!*/ = null; // 3 OuterA.A.ns.Item /*T:string?*/ = null; - B.s.Item /*T:string!*/ = null; // warn 3 + B.s.Item /*T:string!*/ = null; // 4 B.ns.Item /*T:string?*/ = null; - OuterD.D.s.Item /*T:string!*/ = null; // warn 4 + OuterD.D.s.Item /*T:string!*/ = null; // 5 OuterD.D.ns.Item /*T:string?*/ = null; - Oblivious2.s.Item /*T:string!*/ = null; + Oblivious2.s.Item /*T:string!*/ = null; // 6 Oblivious2.ns.Item /*T:string?*/ = null; } } @@ -9743,39 +9743,45 @@ public void M() compilation.VerifyTypes(); compilation.VerifyDiagnostics( - // (11,37): warning CS8618: Non-nullable field 's' is uninitialized. Consider declaring the field as nullable. + // (11,37): warning CS8618: Non-nullable field 's' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. // public static List3 s; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "s").WithArguments("field", "s").WithLocation(11, 37), - // (12,38): warning CS8618: Non-nullable field 'ns' is uninitialized. Consider declaring the field as nullable. + // (12,38): warning CS8618: Non-nullable field 'ns' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. // public static List3 ns; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "ns").WithArguments("field", "ns").WithLocation(12, 38), - // (19,33): warning CS8618: Non-nullable field 's' is uninitialized. Consider declaring the field as nullable. + // (19,33): warning CS8618: Non-nullable field 's' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. // public static List3 s; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "s").WithArguments("field", "s").WithLocation(19, 33), - // (20,34): warning CS8618: Non-nullable field 'ns' is uninitialized. Consider declaring the field as nullable. + // (20,34): warning CS8618: Non-nullable field 'ns' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. // public static List3 ns; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "ns").WithArguments("field", "ns").WithLocation(20, 34), - // (29,37): warning CS8618: Non-nullable field 's' is uninitialized. Consider declaring the field as nullable. + // (29,37): warning CS8618: Non-nullable field 's' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. // public static List3 s; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "s").WithArguments("field", "s").WithLocation(29, 37), - // (31,38): warning CS8618: Non-nullable field 'ns' is uninitialized. Consider declaring the field as nullable. + // (31,38): warning CS8618: Non-nullable field 'ns' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. // public static List3 ns; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "ns").WithArguments("field", "ns").WithLocation(31, 38), // (39,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations 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 + // External.s.Item /*T:string!*/ = null; // 1 Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(48, 41), + // (51,42): warning CS8625: Cannot convert null literal to non-nullable reference type. + // External.fs.Item /*T:string!*/ = null; // 2 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(51, 42), // (54,41): warning CS8625: Cannot convert null literal to non-nullable reference type. - // OuterA.A.s.Item /*T:string!*/ = null; // warn 2 + // OuterA.A.s.Item /*T:string!*/ = null; // 3 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 + // B.s.Item /*T:string!*/ = null; // 4 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)); + // OuterD.D.s.Item /*T:string!*/ = null; // 5 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(60, 41), + // (63,43): warning CS8625: Cannot convert null literal to non-nullable reference type. + // Oblivious2.s.Item /*T:string!*/ = null; // 6 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(63, 43)); } [Fact] @@ -37280,8 +37286,6 @@ public class Derived : Base } "; var comp = CreateNullableCompilation(new[] { NotNullWhenAttributeDefinition, source }); - // Note: we're missing warnings on F1 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 comp.VerifyDiagnostics( // (12,26): warning CS8765: Type of parameter 't2' doesn't match overridden member because of nullability attributes. // public override bool F1(T t1, out T t2, ref T t3, in T t4) => throw null!; // t2, t3 @@ -37366,8 +37370,6 @@ public class Derived : Base public override void F4(T t1, out T t2, ref T t3, in T t4) where T : struct => throw null!; // t1, t4 } "; - // Note: we're missing warnings on F1 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 var comp = CreateCompilation(new[] { NotNullAttributeDefinition, source }); comp.VerifyDiagnostics( // (13,26): warning CS8765: Type of parameter 't1' doesn't match overridden member because of nullability attributes. @@ -38374,7 +38376,7 @@ public class C : I< comp.VerifyDiagnostics(); } - [Fact] + [Fact, WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] public void MaybeNull_Parameter_Generic_OnOverrides() { var source = @@ -38396,20 +38398,24 @@ public class Derived : Base public override void F5([MaybeNull]T? t1, [MaybeNull] out T? t2, [MaybeNull] ref T? t3, [MaybeNull] in T? t4) where T : struct => throw null!; } "; - // Note: we're missing warnings on F1 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 var comp = CreateNullableCompilation(new[] { MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( - // (13,26): error CS8762: Type of parameter 't2' doesn't match overridden member because of nullability attributes. + // (12,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). + // public override void F1([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t2").WithLocation(12, 26), + // (12,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override void F1([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t3").WithLocation(12, 26), + // (13,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). // public override void F2([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) where T : class => throw null!; // t2, t3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t2").WithLocation(13, 26), - // (13,26): error CS8762: Type of parameter 't3' doesn't match overridden member because of nullability attributes. + // (13,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). // public override void F2([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) where T : class => throw null!; // t2, t3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t3").WithLocation(13, 26) ); } - [Fact] + [Fact, WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] public void MaybeNullWhenTrue_Parameter_Generic_OnOverrides() { var source = @@ -38435,13 +38441,17 @@ public class Derived2 : Derived } "; var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, source }); - // Note: we're missing warnings on F1 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 comp.VerifyDiagnostics( - // (13,26): warning CS8765: Type of parameter 't2' doesn't match overridden member because of nullability attributes. + // (12,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F1([MaybeNullWhen(true)]T t1, [MaybeNullWhen(true)] out T t2, [MaybeNullWhen(true)] ref T t3, [MaybeNullWhen(true)] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t2").WithLocation(12, 26), + // (12,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F1([MaybeNullWhen(true)]T t1, [MaybeNullWhen(true)] out T t2, [MaybeNullWhen(true)] ref T t3, [MaybeNullWhen(true)] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t3").WithLocation(12, 26), + // (13,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). // public override bool F2([MaybeNullWhen(true)]T t1, [MaybeNullWhen(true)] out T t2, [MaybeNullWhen(true)] ref T t3, [MaybeNullWhen(true)] in T t4) where T : class => throw null!; // t2, t3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t2").WithLocation(13, 26), - // (13,26): warning CS8765: Type of parameter 't3' doesn't match overridden member because of nullability attributes. + // (13,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). // public override bool F2([MaybeNullWhen(true)]T t1, [MaybeNullWhen(true)] out T t2, [MaybeNullWhen(true)] ref T t3, [MaybeNullWhen(true)] in T t4) where T : class => throw null!; // t2, t3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t3").WithLocation(13, 26) ); @@ -38468,19 +38478,29 @@ public class Derived : Base public override bool F3([MaybeNullWhen(false)]T? t1, [MaybeNullWhen(false)] out T? t2, [MaybeNullWhen(false)] ref T? t3, [MaybeNullWhen(false)] in T? t4) where T : class => throw null!; public override bool F4([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) where T : struct => throw null!; public override bool F5([MaybeNullWhen(false)]T? t1, [MaybeNullWhen(false)] out T? t2, [MaybeNullWhen(false)] ref T? t3, [MaybeNullWhen(false)] in T? t4) where T : struct => throw null!; - public override bool F6([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) => throw null!; + public override bool F6([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) => throw null!; // t2, t3 } "; var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, source }); - // Note: we're missing warnings on F1 and F6 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 comp.VerifyDiagnostics( - // (14,26): warning CS8765: Type of parameter 't2' doesn't match overridden member because of nullability attributes. + // (13,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F1([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t2").WithLocation(13, 26), + // (13,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F1([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t3").WithLocation(13, 26), + // (14,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). // public override bool F2([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) where T : class => throw null!; // t2, t3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t2").WithLocation(14, 26), - // (14,26): warning CS8765: Type of parameter 't3' doesn't match overridden member because of nullability attributes. + // (14,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). // public override bool F2([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) where T : class => throw null!; // t2, t3 - Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t3").WithLocation(14, 26) + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t3").WithLocation(14, 26), + // (18,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F6([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F6").WithArguments("t2").WithLocation(18, 26), + // (18,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F6([MaybeNullWhen(false)]T t1, [MaybeNullWhen(false)] out T t2, [MaybeNullWhen(false)] ref T t3, [MaybeNullWhen(false)] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F6").WithArguments("t3").WithLocation(18, 26) ); } @@ -38508,6 +38528,7 @@ public class Derived : Base } [Fact, WorkItem(41437, "https://github.com/dotnet/roslyn/issues/41437")] + [WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] public void MaybeNullWhenTrue_Parameter_Generic_OnOverrides_WithMaybeNull() { var source = @@ -38528,19 +38549,29 @@ public class Derived : Base public override bool F3([MaybeNull]T? t1, [MaybeNull] out T? t2, [MaybeNull] ref T? t3, [MaybeNull] in T? t4) where T : class => throw null!; public override bool F4([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) where T : struct => throw null!; public override bool F5([MaybeNull]T? t1, [MaybeNull] out T? t2, [MaybeNull] ref T? t3, [MaybeNull] in T? t4) where T : struct => throw null!; - public override bool F6([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; + public override bool F6([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 } "; - // Note: we're missing warnings on F1 and F6 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( - // (14,26): warning CS8765: Type of parameter 't2' doesn't match overridden member because of nullability attributes. + // (13,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F1([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t2").WithLocation(13, 26), + // (13,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F1([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t3").WithLocation(13, 26), + // (14,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). // public override bool F2([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) where T : class => throw null!; // t2, t3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t2").WithLocation(14, 26), - // (14,26): warning CS8765: Type of parameter 't3' doesn't match overridden member because of nullability attributes. + // (14,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). // public override bool F2([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) where T : class => throw null!; // t2, t3 - Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t3").WithLocation(14, 26) + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t3").WithLocation(14, 26), + // (18,26): warning CS8765: Nullability of type of parameter 't2' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F6([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F6").WithArguments("t2").WithLocation(18, 26), + // (18,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override bool F6([MaybeNull]T t1, [MaybeNull] out T t2, [MaybeNull] ref T t3, [MaybeNull] in T t4) => throw null!; // t2, t3 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F6").WithArguments("t3").WithLocation(18, 26) ); } @@ -38635,11 +38666,9 @@ public class Derived : Base comp.VerifyDiagnostics(); } - [Fact] + [Fact, WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] public void DisallowNull_Parameter_Generic_OnOverrides() { - // Note: we're missing warnings on F1 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 var source = @"using System.Diagnostics.CodeAnalysis; public class Base @@ -38661,22 +38690,31 @@ public class Derived : Base "; var comp = CreateNullableCompilation(new[] { DisallowNullAttributeDefinition, source }); comp.VerifyDiagnostics( - // (14,26): warning CS8765: Type of parameter 't1' doesn't match overridden member because of nullability attributes. + // (12,26): warning CS8765: Nullability of type of parameter 't1' doesn't match overridden member (possibly because of nullability attributes). + // public override void F1([DisallowNull]T t1, [DisallowNull] out T t2, [DisallowNull] ref T t3, [DisallowNull] in T t4) => throw null!; // t1, t3, t4 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t1").WithLocation(12, 26), + // (12,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). + // public override void F1([DisallowNull]T t1, [DisallowNull] out T t2, [DisallowNull] ref T t3, [DisallowNull] in T t4) => throw null!; // t1, t3, t4 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t3").WithLocation(12, 26), + // (12,26): warning CS8765: Nullability of type of parameter 't4' doesn't match overridden member (possibly because of nullability attributes). + // public override void F1([DisallowNull]T t1, [DisallowNull] out T t2, [DisallowNull] ref T t3, [DisallowNull] in T t4) => throw null!; // t1, t3, t4 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t4").WithLocation(12, 26), + // (14,26): warning CS8765: Nullability of type of parameter 't1' doesn't match overridden member (possibly because of nullability attributes). // public override void F3([DisallowNull]T? t1, [DisallowNull] out T? t2, [DisallowNull] ref T? t3, [DisallowNull] in T? t4) where T : class => throw null!; // t1, t3, t4 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F3").WithArguments("t1").WithLocation(14, 26), - // (14,26): warning CS8765: Type of parameter 't3' doesn't match overridden member because of nullability attributes. + // (14,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). // public override void F3([DisallowNull]T? t1, [DisallowNull] out T? t2, [DisallowNull] ref T? t3, [DisallowNull] in T? t4) where T : class => throw null!; // t1, t3, t4 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F3").WithArguments("t3").WithLocation(14, 26), - // (14,26): warning CS8765: Type of parameter 't4' doesn't match overridden member because of nullability attributes. + // (14,26): warning CS8765: Nullability of type of parameter 't4' doesn't match overridden member (possibly because of nullability attributes). // public override void F3([DisallowNull]T? t1, [DisallowNull] out T? t2, [DisallowNull] ref T? t3, [DisallowNull] in T? t4) where T : class => throw null!; // t1, t3, t4 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F3").WithArguments("t4").WithLocation(14, 26), - // (16,26): warning CS8765: Type of parameter 't1' doesn't match overridden member because of nullability attributes. + // (16,26): warning CS8765: Nullability of type of parameter 't1' doesn't match overridden member (possibly because of nullability attributes). // public override void F5([DisallowNull]T? t1, [DisallowNull] out T? t2, [DisallowNull] ref T? t3, [DisallowNull] in T? t4) where T : struct => throw null!; // t1, t3, t4 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F5").WithArguments("t1").WithLocation(16, 26), - // (16,26): warning CS8765: Type of parameter 't3' doesn't match overridden member because of nullability attributes. + // (16,26): warning CS8765: Nullability of type of parameter 't3' doesn't match overridden member (possibly because of nullability attributes). // public override void F5([DisallowNull]T? t1, [DisallowNull] out T? t2, [DisallowNull] ref T? t3, [DisallowNull] in T? t4) where T : struct => throw null!; // t1, t3, t4 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F5").WithArguments("t3").WithLocation(16, 26), - // (16,26): warning CS8765: Type of parameter 't4' doesn't match overridden member because of nullability attributes. + // (16,26): warning CS8765: Nullability of type of parameter 't4' doesn't match overridden member (possibly because of nullability attributes). // public override void F5([DisallowNull]T? t1, [DisallowNull] out T? t2, [DisallowNull] ref T? t3, [DisallowNull] in T? t4) where T : struct => throw null!; // t1, t3, t4 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F5").WithArguments("t4").WithLocation(16, 26) ); @@ -43133,7 +43171,7 @@ public class Derived : Base ); } - [Fact] + [Fact, WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] public void NotNull_ReturnValue_GenericType_Loosening_MaybeNull() { var source = @@ -43159,26 +43197,27 @@ public class Derived : Base [return: MaybeNull] public override T F6() => throw null!; // 5 } "; - // Note: we're missing the warning on F6 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, MaybeNullAttributeDefinition, source }); comp.VerifyDiagnostics( - // (14,43): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (14,43): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T F1() => throw null!; // 1 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F1").WithLocation(14, 43), - // (15,43): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (15,43): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T F2() where T : class => throw null!; // 2 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F2").WithLocation(15, 43), - // (16,44): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (16,44): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T? F3() where T : class => throw null!; // 3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F3").WithLocation(16, 44), - // (19,44): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (19,44): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T? F5() where T : struct => throw null!; // 4 - Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F5").WithLocation(19, 44) + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F5").WithLocation(19, 44), + // (20,43): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). + // [return: MaybeNull] public override T F6() => throw null!; // 5 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F6").WithLocation(20, 43) ); } - [Fact] + [Fact, WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] public void NotNull_ReturnValue_GenericType_Loosening_MaybeNull_FromMetadata() { var source = @@ -43210,22 +43249,23 @@ public class Derived : Base [return: MaybeNull] public override T F6() => throw null!; // 5 } "; - // Note: we're missing the warning on F6 because the overridden method with substituted T from Derived has an oblivious T - // https://github.com/dotnet/roslyn/issues/41368 var comp2 = CreateNullableCompilation(source2, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( - // (4,43): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (4,43): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T F1() => throw null!; // 1 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F1").WithLocation(4, 43), - // (5,43): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (5,43): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T F2() where T : class => throw null!; // 2 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F2").WithLocation(5, 43), - // (6,44): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (6,44): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T? F3() where T : class => throw null!; // 3 Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F3").WithLocation(6, 44), - // (9,44): warning CS8764: Return type doesn't match overridden member because of nullability attributes. + // (9,44): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). // [return: MaybeNull] public override T? F5() where T : struct => throw null!; // 4 - Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F5").WithLocation(9, 44) + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F5").WithLocation(9, 44), + // (10,43): warning CS8764: Nullability of return type doesn't match overridden member (possibly because of nullability attributes). + // [return: MaybeNull] public override T F6() => throw null!; // 5 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnOverride, "F6").WithLocation(10, 43) ); } @@ -45476,23 +45516,23 @@ 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 + _ = (true ? k => s : D1(s)) /*T:System.Func!*/; // 1 // unexpected type + _ = (false ? D1(s) : k => s) /*T:System.Func!*/; // 2 // 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(s!) : k => s) /*T:System.Func!*/; // 3, unexpected type + _ = (b ? k => s : D1(s!)) /*T:System.Func!*/; // 4, unexpected type + _ = (true ? D1(s!) : k => s) /*T:System.Func!*/; // unexpected type + _ = (true ? k => s : D1(s!)) /*T:System.Func!*/; // 5, unexpected type + _ = (false ? D1(s!) : k => s) /*T:System.Func!*/; // 6, 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 + _ = (b ? D1(true ? throw null! : s) : k => s) /*T:System.Func!*/; // 7, unexpected type + _ = (b ? k => s : D1(true ? throw null! : s)) /*T:System.Func!*/; // 8, 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!*/; // unexpected type + _ = (false ? D1(true ? throw null! : s) : k => s) /*T:System.Func!*/; // 9, unexpected type + _ = (false ? k => s : D1(true ? throw null! : s)) /*T:System.Func!*/; // unexpected type } delegate T MyDelegate(bool b); @@ -45500,33 +45540,57 @@ void M1(bool b, string? s) 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 + _ = (b ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 10 + _ = (b ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 11 + _ = (true ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 12 _ = (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 + _ = (false ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 13 } }"; // See https://github.com/dotnet/roslyn/issues/34392 - // Best type inference involving lambda conversion should agree with method type inference + // Best type inference involving lambda conversion should agree with method type inference and properly account for return type with nullability from lambda // Missing diagnostics var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); comp.VerifyDiagnostics( + // (12,26): warning CS8603: Possible null reference return. + // _ = (true ? k => s : D1(s)) /*T:System.Func!*/; // 1 // unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(12, 26), + // (13,35): warning CS8603: Possible null reference return. + // _ = (false ? D1(s) : k => s) /*T:System.Func!*/; // 2 // unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(13, 35), + // (16,32): warning CS8603: Possible null reference return. + // _ = (b ? D1(s!) : k => s) /*T:System.Func!*/; // 3, unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(16, 32), + // (17,23): warning CS8603: Possible null reference return. + // _ = (b ? k => s : D1(s!)) /*T:System.Func!*/; // 4, unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(17, 23), + // (19,26): warning CS8603: Possible null reference return. + // _ = (true ? k => s : D1(s!)) /*T:System.Func!*/; // 5, unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(19, 26), + // (20,36): warning CS8603: Possible null reference return. + // _ = (false ? D1(s!) : k => s) /*T:System.Func!*/; // 6, unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(20, 36), + // (23,52): warning CS8603: Possible null reference return. + // _ = (b ? D1(true ? throw null! : s) : k => s) /*T:System.Func!*/; // 7, unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(23, 52), + // (24,23): warning CS8603: Possible null reference return. + // _ = (b ? k => s : D1(true ? throw null! : s)) /*T:System.Func!*/; // 8, unexpected type + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(24, 23), // (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 + // _ = (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(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 + // _ = (b ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 11 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 + // _ = (true ? ref D2(s) : ref D2(s!)) /*T:C.MyDelegate!*/; // 12 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 + // _ = (false ? ref D2(s!) : ref D2(s)) /*T:C.MyDelegate!*/; // 13 Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "false ? ref D2(s!) : ref D2(s)").WithArguments("C.MyDelegate", "C.MyDelegate").WithLocation(41, 14) ); } @@ -54616,19 +54680,44 @@ void M1(bool b, string? s, string s2) M2(k => s2, D1(s2)) /*T:System.Func!*/; M2(D1(s2), k => s2) /*T:System.Func!*/; + M2(k => s, D1(s2)) /*T:System.Func!*/; // wrong + M2(D1(s), k => s2) /*T:System.Func!*/; + + M2(k => s2, D1(s)) /*T:System.Func!*/; + M2(D1(s2), k => s) /*T:System.Func!*/; // wrong + _ = (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 + _ = (new[] { k => s2, D1(s2) }) /*T:System.Func![]!*/; + _ = (new[] { D1(s2), k => s2 }) /*T:System.Func![]!*/; + + _ = (new[] { k => s, D1(s2) }) /*T:System.Func![]!*/; // wrong + _ = (new[] { D1(s), k => s2 }) /*T:System.Func![]!*/; + + _ = (new[] { k => s2, D1(s) }) /*T:System.Func![]!*/; + _ = (new[] { D1(s2), k => s }) /*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 + // Best type inference involving lambda conversion should account for proper return type with nullability from lambda var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyTypes(); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (13,17): warning CS8603: Possible null reference return. + // M2(k => s, D1(s2)) /*T:System.Func!*/; // wrong + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(13, 17), + // (17,25): warning CS8603: Possible null reference return. + // M2(D1(s2), k => s) /*T:System.Func!*/; // wrong + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(17, 25), + // (25,27): warning CS8603: Possible null reference return. + // _ = (new[] { k => s, D1(s2) }) /*T:System.Func![]!*/; // wrong + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(25, 27), + // (29,35): warning CS8603: Possible null reference return. + // _ = (new[] { D1(s2), k => s }) /*T:System.Func![]!*/; // wrong + Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s").WithLocation(29, 35) + ); } // Multiple returns, one of which is null. @@ -79028,11 +79117,11 @@ 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!*/; + var xz = CreateIOut(x, z)/*T:IOut!*/; F(xx, xy)/*T:IOut!*/; - F(xx, xz)/*T:IOut!*/; + F(xx, xz)/*T:IOut!*/; F(CreateIOut(y, x), xx)/*T:IOut!*/; - F(CreateIOut(y, z), CreateIOut(z, x))/*T:IOut!*/; + F(CreateIOut(y, z), CreateIOut(z, x))/*T:IOut!*/; F(xx, xy, xz)/*T:IOut!*/; } }"; @@ -79335,16 +79424,19 @@ static void G(string? x, string y) 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(x))/*T:string!*/; // 2 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)'. + // (13,25): warning CS8620: Argument of type 'B' cannot be used for parameter 'y' of type 'B' in 'string C.F(IIn x, B y)' due to differences in the nullability of reference types. // 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) + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(x)").WithArguments("B", "B", "y", "string C.F(IIn x, B y)").WithLocation(13, 25), + // (16,25): warning CS8620: Argument of type 'B' cannot be used for parameter 'y' of type 'B' in 'string C.F(IIn x, B y)' due to differences in the nullability of reference types. + // F(zin, CreateB(x))/*T:string!*/; // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "CreateB(x)").WithArguments("B", "B", "y", "string C.F(IIn x, B y)").WithLocation(16, 25) ); comp.VerifyTypes(); } @@ -79572,31 +79664,40 @@ static void G(A t1, A t2, A u1, A u2) 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!*/; + var z = CreateB(t1, u3)/*T:B!*/; + var w = CreateB(t3, u2)/*T:B!*/; + F(x, y)/*T:B!*/; // 1, 2 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!*/; + F(x, w)/*T:B!*/; // 3 + F(y, z)/*T:B!*/; // 4, 5 + F(y, w)/*T:B!*/; // 6 + F(w, z)/*T:B!*/; // 7 } }"; 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!*/; + // (13,11): warning CS8620: Argument of type 'B' cannot be used for parameter 'x' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(x, y)/*T:B!*/; // 1, 2 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!*/; + // (13,14): warning CS8620: Argument of type 'B' cannot be used for parameter 'y' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(x, y)/*T:B!*/; // 1, 2 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) + // (15,11): warning CS8620: Argument of type 'B' cannot be used for parameter 'x' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(x, w)/*T:B!*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(15, 11), + // (16,11): warning CS8620: Argument of type 'B' cannot be used for parameter 'x' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(y, z)/*T:B!*/; // 4, 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(16, 11), + // (16,14): warning CS8620: Argument of type 'B' cannot be used for parameter 'y' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(y, z)/*T:B!*/; // 4, 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(16, 14), + // (17,11): warning CS8620: Argument of type 'B' cannot be used for parameter 'x' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(y, w)/*T:B!*/; // 6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "B", "x", "B C.F>(B x, B y)").WithLocation(17, 11), + // (18,14): warning CS8620: Argument of type 'B' cannot be used for parameter 'y' of type 'B' in 'B C.F>(B x, B y)' due to differences in the nullability of reference types. + // F(w, z)/*T:B!*/; // 7 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("B", "B", "y", "B C.F>(B x, B y)").WithLocation(18, 14) ); } @@ -79628,31 +79729,40 @@ static void G(X t1, X t2, X u1, X u2) 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 + 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!*/; + F(x, w)/*T:B!*/; // 3 + F(y, z)/*T:B!*/; // 4, 5 + F(y, w)/*T:B!*/; // 6 + F(w, z)/*T:B!*/; // 7 } }"; 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 + // (13,11): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'x' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // 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 + // (13,14): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'y' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // 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) + // (15,11): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'x' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // F(x, w)/*T:B!*/; // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(15, 11), + // (16,11): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'x' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // F(y, z)/*T:B!*/; // 4, 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(16, 11), + // (16,14): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'y' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // F(y, z)/*T:B!*/; // 4, 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(16, 14), + // (17,11): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'x' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // F(y, w)/*T:B!*/; // 6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("IIn>", "IIn>", "x", "B C.F>(IIn> x, IIn> y)").WithLocation(17, 11), + // (18,14): warning CS8620: Argument of type 'IIn>' cannot be used for parameter 'y' of type 'IIn>' in 'B C.F>(IIn> x, IIn> y)' due to differences in the nullability of reference types. + // F(w, z)/*T:B!*/; // 7 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("IIn>", "IIn>", "y", "B C.F>(IIn> x, IIn> y)").WithLocation(18, 14) ); } @@ -79829,14 +79939,14 @@ static void G(B t1, B t2, B u1, B u2) 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!)*/; + 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, 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)*/; + F(y, w)/*T:(object!, string?)*/; + F(w, z)/*T:(object?, string!)*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue(), references: new[] { ref0 }); @@ -86675,8 +86785,8 @@ void symbolValidator(ModuleSymbol m) { 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); + Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!", impl.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(impl.TypeParameters[0].IsNotNullable); } var bf1 = (MethodSymbol)m.GlobalNamespace.GetMember("B.I.F1"); @@ -86706,8 +86816,8 @@ void symbolValidator(ModuleSymbol m) 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); + Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!", impl.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(impl.TypeParameters[0].IsNotNullable); } } } @@ -86764,12 +86874,12 @@ void symbolValidator(ModuleSymbol m) if (isSource) { Assert.Empty(at1.GetAttributes()); - Assert.Equal("void I.F1(TF1 x) where TF1 : A!", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + 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)); + 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"); @@ -86796,7 +86906,7 @@ void symbolValidator(ModuleSymbol m) else { Assert.Empty(tf1.GetAttributes()); - Assert.Equal("void I.F1(TF1 x) where TF1 : A", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.Equal("void I.F1(TF1! x) where TF1 : A!", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } @@ -86851,11 +86961,11 @@ void symbolValidator(ModuleSymbol m) if (isSource) { - Assert.Equal("void I.F1(TF1 x) where TF1 : class?, System.Object!", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + 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)); + 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"); @@ -86879,7 +86989,7 @@ void symbolValidator(ModuleSymbol m) } else { - Assert.Equal("void I.F1(TF1 x) where TF1 : class?, System.Object", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.Equal("void I.F1(TF1! x) where TF1 : class?, System.Object!", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } @@ -87037,11 +87147,11 @@ void symbolValidator(ModuleSymbol m) if (isSource) { - Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!, B?", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + 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)); + 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"); @@ -87065,7 +87175,7 @@ void symbolValidator(ModuleSymbol m) } else { - Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object, B?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.Equal("void I.F1(TF1! x) where TF1 : System.Object!, B?", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } @@ -87119,11 +87229,11 @@ void symbolValidator(ModuleSymbol m) if (isSource) { - Assert.Equal("void I.F1(TF1 x) where TF1 : System.Object!, B?", af1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + 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)); + 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"); @@ -87147,7 +87257,7 @@ void symbolValidator(ModuleSymbol m) } else { - Assert.Equal("void I.F1(TF1 x) where TF1 : B", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.Equal("void I.F1(TF1! x) where TF1 : B!", bf1.ExplicitInterfaceImplementations.Single().ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); } } } @@ -92050,7 +92160,7 @@ public class Test61 : Test6 { public void Test() { - M1(new object()); + M1(new object()); // 7 } } @@ -92064,7 +92174,7 @@ public override void M1(S x) public void Test() { - M1(new object()); + M1(new object()); // 8 } } @@ -92072,7 +92182,7 @@ public class Test71 : Test7 { public void Test() { - M1(new object()); + M1(new object()); // 9 } } @@ -92086,7 +92196,7 @@ public override void M1(S x) public void Test() { - M1(new object()); + M1(new object()); // 10 } } "; @@ -92112,7 +92222,19 @@ public void Test() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(59, 9), // (81,9): warning CS8602: Dereference of a possibly null reference. // x.ToString(); // 6 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(81, 9) + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(81, 9), + // (95,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()); // 7 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test1.M1(S)", "object", "S", "object?").WithLocation(95, 9), + // (109,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test62.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. + // M1(new object()); // 8 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test62.M1(S)", "object", "S", "object?").WithLocation(109, 9), + // (117,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test7.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. + // M1(new object()); // 9 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test7.M1(S)", "object", "S", "object?").WithLocation(117, 9), + // (131,9): warning CS8631: The type 'object?' cannot be used as type parameter 'S' in the generic type or method 'Test72.M1(S)'. Nullability of type argument 'object?' doesn't match constraint type 'object'. + // M1(new object()); // 10 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "M1").WithArguments("Test72.M1(S)", "object", "S", "object?").WithLocation(131, 9) ); } } @@ -92269,8 +92391,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -92460,8 +92582,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : class?, System.Object!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -93161,8 +93283,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : class?, System.Object!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -93198,8 +93320,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -93234,8 +93356,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : System.Object!, I1?", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -93471,8 +93593,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S! x) where S : I1?, System.String!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -93507,8 +93629,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : I1?, System.String!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -93688,8 +93810,8 @@ public override void M1(S x) 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); + Assert.Equal("void Test2.M1(S x) where S : I1?, System.String!", m1.ToDisplayString(SymbolDisplayFormat.TestFormatWithConstraints)); + Assert.True(m1.TypeParameters[0].IsNotNullable); } } @@ -97676,10 +97798,9 @@ public override void F4() { } 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.F3", "System.String!", "I!"); verifyConstraintTypes("B1.F4", "System.String?", "I!"); verifyConstraintTypes("B2.F1", "System.String?", "I"); verifyConstraintTypes("B2.F2", "System.String?", "I"); @@ -126444,6 +126565,9 @@ static void M3( }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( + // (41,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. + // _ = x - z; + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator -(C a, C b)").WithLocation(41, 17), // (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), @@ -126512,6 +126636,9 @@ static void M3( }"; 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. + // _ = x * z; + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator *(C a, C b)").WithLocation(44, 17), // (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), @@ -126621,6 +126748,9 @@ static void M2( }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( + // (30,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. + // _ = x - z; + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "z").WithArguments("C", "C", "b", "C C.operator -(C a, C b)").WithLocation(30, 17), // (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), @@ -131814,12 +131944,12 @@ class Program var ay = CreateA(y); var by = CreateB(y); (ax + bx).F.ToString(); // 2 - (ax + by).F.ToString(); // 3 - (ay + bx).F.ToString(); // 4 + (ax + by).F.ToString(); // 3, 4 + (ay + bx).F.ToString(); // 5 (ay + by).F.ToString(); - (ax * bx).F.ToString(); // 5 - (ax * by).F.ToString(); // 6 - (ay * bx).F.ToString(); // 7 + (ax * bx).F.ToString(); // 6 + (ax * by).F.ToString(); // 7 + (ay * bx).F.ToString(); // 8, 9 (ay * by).F.ToString(); } }"; @@ -131832,25 +131962,25 @@ class Program // (ax + bx).F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(ax + bx).F").WithLocation(24, 9), // (25,9): warning CS8602: Dereference of a possibly null reference. - // (ax + by).F.ToString(); // 3 + // (ax + by).F.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(ax + by).F").WithLocation(25, 9), // (25,15): warning CS8620: Argument of type 'B' cannot be used for parameter 'b' of type 'B' in 'A A.operator +(A a, B b)' due to differences in the nullability of reference types. - // (ax + by).F.ToString(); // 3 + // (ax + by).F.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "by").WithArguments("B", "B", "b", "A A.operator +(A a, B b)").WithLocation(25, 15), // (26,15): warning CS8620: Argument of type 'B' cannot be used for parameter 'b' of type 'B' in 'A A.operator +(A a, B b)' due to differences in the nullability of reference types. - // (ay + bx).F.ToString(); // 4 + // (ay + bx).F.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "bx").WithArguments("B", "B", "b", "A A.operator +(A a, B b)").WithLocation(26, 15), // (28,9): warning CS8602: Dereference of a possibly null reference. - // (ax * bx).F.ToString(); // 5 + // (ax * bx).F.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(ax * bx).F").WithLocation(28, 9), // (29,10): warning CS8620: Argument of type 'A' cannot be used for parameter 'a' of type 'A' in 'A B.operator *(A a, B b)' due to differences in the nullability of reference types. - // (ax * by).F.ToString(); // 6 + // (ax * by).F.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "a", "A B.operator *(A a, B b)").WithLocation(29, 10), // (30,9): warning CS8602: Dereference of a possibly null reference. - // (ay * bx).F.ToString(); // 7 + // (ay * bx).F.ToString(); // 8, 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(ay * bx).F").WithLocation(30, 9), // (30,10): warning CS8620: Argument of type 'A' cannot be used for parameter 'a' of type 'A' in 'A B.operator *(A a, B b)' due to differences in the nullability of reference types. - // (ay * bx).F.ToString(); // 7 + // (ay * bx).F.ToString(); // 8, 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ay").WithArguments("A", "A", "a", "A B.operator *(A a, B b)").WithLocation(30, 10)); } @@ -131890,12 +132020,12 @@ class Program var b1y = Create1(y); var b2y = Create2(y); (b1x + b1x).F.ToString(); // 2 - (b1x + b1y).F.ToString(); // 3 - (b1y + b1x).F.ToString(); // 4 + (b1x + b1y).F.ToString(); // 3, 4 + (b1y + b1x).F.ToString(); // 5 (b1y + b1y).F.ToString(); - (b2x * b2x).F.ToString(); // 5 - (b2x * b2y).F.ToString(); // 6 - (b2y * b2x).F.ToString(); // 7 + (b2x * b2x).F.ToString(); // 6 + (b2x * b2y).F.ToString(); // 7, 8 + (b2y * b2x).F.ToString(); // 9 (b2y * b2y).F.ToString(); } }"; @@ -131908,25 +132038,25 @@ class Program // (b1x + b1x).F.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b1x + b1x).F").WithLocation(31, 9), // (32,9): warning CS8602: Dereference of a possibly null reference. - // (b1x + b1y).F.ToString(); // 3 + // (b1x + b1y).F.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b1x + b1y).F").WithLocation(32, 9), // (32,16): warning CS8620: Argument of type 'B1' cannot be used for parameter 'b' of type 'B1' in 'A1 A1.operator +(A1 a, B1 b)' due to differences in the nullability of reference types. - // (b1x + b1y).F.ToString(); // 3 + // (b1x + b1y).F.ToString(); // 3, 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b1y").WithArguments("B1", "B1", "b", "A1 A1.operator +(A1 a, B1 b)").WithLocation(32, 16), // (33,16): warning CS8620: Argument of type 'B1' cannot be used for parameter 'b' of type 'B1' in 'A1 A1.operator +(A1 a, B1 b)' due to differences in the nullability of reference types. - // (b1y + b1x).F.ToString(); // 4 + // (b1y + b1x).F.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b1x").WithArguments("B1", "B1", "b", "A1 A1.operator +(A1 a, B1 b)").WithLocation(33, 16), // (35,9): warning CS8602: Dereference of a possibly null reference. - // (b2x * b2x).F.ToString(); // 5 + // (b2x * b2x).F.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b2x * b2x).F").WithLocation(35, 9), // (36,9): warning CS8602: Dereference of a possibly null reference. - // (b2x * b2y).F.ToString(); // 6 + // (b2x * b2y).F.ToString(); // 7, 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(b2x * b2y).F").WithLocation(36, 9), // (36,16): warning CS8620: Argument of type 'B2' cannot be used for parameter 'b' of type 'B2' in 'A2 A2.operator *(A2 a, B2 b)' due to differences in the nullability of reference types. - // (b2x * b2y).F.ToString(); // 6 + // (b2x * b2y).F.ToString(); // 7, 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b2y").WithArguments("B2", "B2", "b", "A2 A2.operator *(A2 a, B2 b)").WithLocation(36, 16), // (37,16): warning CS8620: Argument of type 'B2' cannot be used for parameter 'b' of type 'B2' in 'A2 A2.operator *(A2 a, B2 b)' due to differences in the nullability of reference types. - // (b2y * b2x).F.ToString(); // 7 + // (b2y * b2x).F.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b2x").WithArguments("B2", "B2", "b", "A2 A2.operator *(A2 a, B2 b)").WithLocation(37, 16)); } @@ -131954,14 +132084,14 @@ class Program var s2x = Create2(x); var s1y = Create1(y); var s2y = Create2(y); - (s1x + s1y).F.ToString(); - (s1y + s1x).F.ToString(); - (s1x + s2y).Value.F.ToString(); - (s1y + s2x).Value.F.ToString(); - (s2x + s1y).Value.F.ToString(); - (s2y + s1x).Value.F.ToString(); - (s2x + s2y).Value.F.ToString(); - (s2y + s2x).Value.F.ToString(); + (s1x + s1y).F.ToString(); // 2, 3 + (s1y + s1x).F.ToString(); // 4 + (s1x + s2y).Value.F.ToString(); // 5, 6, 7 + (s1y + s2x).Value.F.ToString(); // 8, 9 + (s2x + s1y).Value.F.ToString(); // 10, 11, 12 + (s2y + s1x).Value.F.ToString(); // 13, 14 + (s2x + s2y).Value.F.ToString(); // 15, 16, 17 + (s2y + s2x).Value.F.ToString(); // 18, 19 } }"; var comp = CreateCompilation(source); @@ -131970,58 +132100,58 @@ class Program // T x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(14, 15), // (20,9): warning CS8602: Dereference of a possibly null reference. - // (s1x + s1y).F.ToString(); + // (s1x + s1y).F.ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s1x + s1y).F").WithLocation(20, 9), // (20,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s1x + s1y).F.ToString(); + // (s1x + s1y).F.ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1y").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(20, 16), // (21,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s1y + s1x).F.ToString(); + // (s1y + s1x).F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1x").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(21, 16), // (22,9): warning CS8602: Dereference of a possibly null reference. - // (s1x + s2y).Value.F.ToString(); + // (s1x + s2y).Value.F.ToString(); // 5, 6, 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s1x + s2y).Value.F").WithLocation(22, 9), // (22,10): warning CS8629: Nullable value type may be null. - // (s1x + s2y).Value.F.ToString(); + // (s1x + s2y).Value.F.ToString(); // 5, 6, 7 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1x + s2y").WithLocation(22, 10), // (22,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s1x + s2y).Value.F.ToString(); + // (s1x + s2y).Value.F.ToString(); // 5, 6, 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2y").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(22, 16), // (23,10): warning CS8629: Nullable value type may be null. - // (s1y + s2x).Value.F.ToString(); + // (s1y + s2x).Value.F.ToString(); // 8, 9 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s1y + s2x").WithLocation(23, 10), // (23,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s1y + s2x).Value.F.ToString(); + // (s1y + s2x).Value.F.ToString(); // 8, 9 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2x").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(23, 16), // (24,9): warning CS8602: Dereference of a possibly null reference. - // (s2x + s1y).Value.F.ToString(); + // (s2x + s1y).Value.F.ToString(); // 10, 11, 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s2x + s1y).Value.F").WithLocation(24, 9), // (24,10): warning CS8629: Nullable value type may be null. - // (s2x + s1y).Value.F.ToString(); + // (s2x + s1y).Value.F.ToString(); // 10, 11, 12 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2x + s1y").WithLocation(24, 10), // (24,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s2x + s1y).Value.F.ToString(); + // (s2x + s1y).Value.F.ToString(); // 10, 11, 12 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1y").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(24, 16), // (25,10): warning CS8629: Nullable value type may be null. - // (s2y + s1x).Value.F.ToString(); + // (s2y + s1x).Value.F.ToString(); // 13, 14 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2y + s1x").WithLocation(25, 10), // (25,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s2y + s1x).Value.F.ToString(); + // (s2y + s1x).Value.F.ToString(); // 13, 14 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1x").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(25, 16), // (26,9): warning CS8602: Dereference of a possibly null reference. - // (s2x + s2y).Value.F.ToString(); + // (s2x + s2y).Value.F.ToString(); // 15, 16, 17 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s2x + s2y).Value.F").WithLocation(26, 9), // (26,10): warning CS8629: Nullable value type may be null. - // (s2x + s2y).Value.F.ToString(); + // (s2x + s2y).Value.F.ToString(); // 15, 16, 17 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2x + s2y").WithLocation(26, 10), // (26,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s2x + s2y).Value.F.ToString(); + // (s2x + s2y).Value.F.ToString(); // 15, 16, 17 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2y").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(26, 16), // (27,10): warning CS8629: Nullable value type may be null. - // (s2y + s2x).Value.F.ToString(); + // (s2y + s2x).Value.F.ToString(); // 18, 19 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2y + s2x").WithLocation(27, 10), // (27,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S S.operator +(S x, S y)' due to differences in the nullability of reference types. - // (s2y + s2x).Value.F.ToString(); + // (s2y + s2x).Value.F.ToString(); // 18, 19 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2x").WithArguments("S", "S", "y", "S S.operator +(S x, S y)").WithLocation(27, 16)); } @@ -132050,17 +132180,17 @@ class Program var s2x = Create2(x); var s1y = Create1(y); var s2y = Create2(y); - (s1x + s1y).Value.F.ToString(); - (s1x + s2x).Value.F.ToString(); - (s1x + s2y).Value.F.ToString(); - (s1y + s1x).Value.F.ToString(); - (s1y + s2x).Value.F.ToString(); + (s1x + s1y).Value.F.ToString(); // 2, 3 + (s1x + s2x).Value.F.ToString(); // 4 + (s1x + s2y).Value.F.ToString(); // 5, 6 + (s1y + s1x).Value.F.ToString(); // 7 + (s1y + s2x).Value.F.ToString(); // 8 (s1y + s2y).Value.F.ToString(); - (s1x * s1y).Value.F.ToString(); - (s1y * s1x).Value.F.ToString(); - (s2x * s1x).Value.F.ToString(); - (s2x * s1y).Value.F.ToString(); - (s2y * s1x).Value.F.ToString(); + (s1x * s1y).Value.F.ToString(); // 9, 10 + (s1y * s1x).Value.F.ToString(); // 11 + (s2x * s1x).Value.F.ToString(); // 12 + (s2x * s1y).Value.F.ToString(); // 13, 14 + (s2y * s1x).Value.F.ToString(); // 15 (s2y * s1y).Value.F.ToString(); } }"; @@ -132070,46 +132200,46 @@ class Program // T x = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(15, 15), // (21,9): warning CS8602: Dereference of a possibly null reference. - // (s1x + s1y).Value.F.ToString(); + // (s1x + s1y).Value.F.ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s1x + s1y).Value.F").WithLocation(21, 9), // (21,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S?' in 'S? S.operator +(S x, S? y)' due to differences in the nullability of reference types. - // (s1x + s1y).Value.F.ToString(); + // (s1x + s1y).Value.F.ToString(); // 2, 3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1y").WithArguments("S", "S?", "y", "S? S.operator +(S x, S? y)").WithLocation(21, 16), // (22,9): warning CS8602: Dereference of a possibly null reference. - // (s1x + s2x).Value.F.ToString(); + // (s1x + s2x).Value.F.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s1x + s2x).Value.F").WithLocation(22, 9), // (23,9): warning CS8602: Dereference of a possibly null reference. - // (s1x + s2y).Value.F.ToString(); + // (s1x + s2y).Value.F.ToString(); // 5, 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s1x + s2y).Value.F").WithLocation(23, 9), // (23,16): warning CS8620: Argument of type 'S?' cannot be used for parameter 'y' of type 'S?' in 'S? S.operator +(S x, S? y)' due to differences in the nullability of reference types. - // (s1x + s2y).Value.F.ToString(); + // (s1x + s2y).Value.F.ToString(); // 5, 6 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2y").WithArguments("S?", "S?", "y", "S? S.operator +(S x, S? y)").WithLocation(23, 16), // (24,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S?' in 'S? S.operator +(S x, S? y)' due to differences in the nullability of reference types. - // (s1y + s1x).Value.F.ToString(); + // (s1y + s1x).Value.F.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1x").WithArguments("S", "S?", "y", "S? S.operator +(S x, S? y)").WithLocation(24, 16), // (25,16): warning CS8620: Argument of type 'S?' cannot be used for parameter 'y' of type 'S?' in 'S? S.operator +(S x, S? y)' due to differences in the nullability of reference types. - // (s1y + s2x).Value.F.ToString(); + // (s1y + s2x).Value.F.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s2x").WithArguments("S?", "S?", "y", "S? S.operator +(S x, S? y)").WithLocation(25, 16), // (27,9): warning CS8602: Dereference of a possibly null reference. - // (s1x * s1y).Value.F.ToString(); + // (s1x * s1y).Value.F.ToString(); // 9, 10 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s1x * s1y).Value.F").WithLocation(27, 9), // (27,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S? S.operator *(S? x, S y)' due to differences in the nullability of reference types. - // (s1x * s1y).Value.F.ToString(); + // (s1x * s1y).Value.F.ToString(); // 9, 10 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1y").WithArguments("S", "S", "y", "S? S.operator *(S? x, S y)").WithLocation(27, 16), // (28,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S? S.operator *(S? x, S y)' due to differences in the nullability of reference types. - // (s1y * s1x).Value.F.ToString(); + // (s1y * s1x).Value.F.ToString(); // 11 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1x").WithArguments("S", "S", "y", "S? S.operator *(S? x, S y)").WithLocation(28, 16), // (29,9): warning CS8602: Dereference of a possibly null reference. - // (s2x * s1x).Value.F.ToString(); + // (s2x * s1x).Value.F.ToString(); // 12 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s2x * s1x).Value.F").WithLocation(29, 9), // (30,9): warning CS8602: Dereference of a possibly null reference. - // (s2x * s1y).Value.F.ToString(); + // (s2x * s1y).Value.F.ToString(); // 13, 14 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(s2x * s1y).Value.F").WithLocation(30, 9), // (30,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S? S.operator *(S? x, S y)' due to differences in the nullability of reference types. - // (s2x * s1y).Value.F.ToString(); + // (s2x * s1y).Value.F.ToString(); // 13, 14 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1y").WithArguments("S", "S", "y", "S? S.operator *(S? x, S y)").WithLocation(30, 16), // (31,16): warning CS8620: Argument of type 'S' cannot be used for parameter 'y' of type 'S' in 'S? S.operator *(S? x, S y)' due to differences in the nullability of reference types. - // (s2y * s1x).Value.F.ToString(); + // (s2y * s1x).Value.F.ToString(); // 15 Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1x").WithArguments("S", "S", "y", "S? S.operator *(S? x, S y)").WithLocation(31, 16)); } @@ -132152,11 +132282,39 @@ class Program } }"; var comp = CreateCompilation(source); + // TODO2 Incorrect warnings are due to failure to update operator based on operand types in NullableWalker.AfterLeftChildHasBeenVisited // https://github.com/dotnet/roslyn/issues/29605: Missing warnings. comp.VerifyDiagnostics( // (20,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x = null; // 1 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(20, 15)); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(20, 15), + // (26,14): warning CS8620: Argument of type 'A' cannot be used for parameter 'a' of type 'A' in 'bool A.operator false(A a)' due to differences in the nullability of reference types. + // _ = (ax && ay); // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "a", "bool A.operator false(A a)").WithLocation(26, 14), + // (26,14): warning CS8620: Argument of type 'A' cannot be used for parameter 'x' of type 'A' in 'A A.operator &(A x, A y)' due to differences in the nullability of reference types. + // _ = (ax && ay); // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "x", "A A.operator &(A x, A y)").WithLocation(26, 14), + // (27,14): warning CS8620: Argument of type 'A' cannot be used for parameter 'a' of type 'A' in 'bool A.operator false(A a)' due to differences in the nullability of reference types. + // _ = (ax && bx); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "a", "bool A.operator false(A a)").WithLocation(27, 14), + // (27,14): warning CS8620: Argument of type 'A' cannot be used for parameter 'x' of type 'A' in 'A A.operator &(A x, A y)' due to differences in the nullability of reference types. + // _ = (ax && bx); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "x", "A A.operator &(A x, A y)").WithLocation(27, 14), + // (27,20): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. + // _ = (ax && bx); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "bx").WithArguments("B", "A").WithLocation(27, 20), + // (28,14): warning CS8620: Argument of type 'A' cannot be used for parameter 'a' of type 'A' in 'bool A.operator true(A a)' due to differences in the nullability of reference types. + // _ = (ax || by); // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "a", "bool A.operator true(A a)").WithLocation(28, 14), + // (28,14): warning CS8620: Argument of type 'A' cannot be used for parameter 'x' of type 'A' in 'A A.operator |(A x, A y)' due to differences in the nullability of reference types. + // _ = (ax || by); // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "x", "A A.operator |(A x, A y)").WithLocation(28, 14), + // (29,20): warning CS8620: Argument of type 'A' cannot be used for parameter 'y' of type 'A' in 'A A.operator &(A x, A y)' due to differences in the nullability of reference types. + // _ = (by && ax); // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "ax").WithArguments("A", "A", "y", "A A.operator &(A x, A y)").WithLocation(29, 20), + // (31,20): warning CS8619: Nullability of reference types in value of type 'B' doesn't match target type 'A'. + // _ = (by || bx); // 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "bx").WithArguments("B", "A").WithLocation(31, 20)); } [Fact] @@ -132195,11 +132353,24 @@ class Program } }"; var comp = CreateCompilation(source); + // TODO2 Incorrect warnings are due to failure to update operator based on operand types in NullableWalker.AfterLeftChildHasBeenVisited // https://github.com/dotnet/roslyn/issues/29605: Missing warnings. comp.VerifyDiagnostics( // (17,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T x = null; // 1 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(17, 15)); + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(17, 15), + // (23,14): warning CS8620: Argument of type 'S' cannot be used for parameter 'x' of type 'S' in 'S S.operator &(S x, S y)' due to differences in the nullability of reference types. + // _ = (s1x && s1y); // 2 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "s1x").WithArguments("S", "S", "x", "S S.operator &(S x, S y)").WithLocation(23, 14), + // (24,14): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S?'. + // _ = (s1x && s2x); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "s1x").WithArguments("S", "S?").WithLocation(24, 14), + // (25,14): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S?'. + // _ = (s1x || s2y); // 3 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "s1x").WithArguments("S", "S?").WithLocation(25, 14), + // (26,21): warning CS8619: Nullability of reference types in value of type 'S' doesn't match target type 'S?'. + // _ = (s2y && s1x); // 4 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "s1x").WithArguments("S", "S?").WithLocation(26, 21)); } [Fact] @@ -132391,6 +132562,7 @@ static async Task Main() } } }"; + // TODO2 there's a problem in nullability analysis of await foreach var comp = CreateCompilationWithTasksExtensions(new[] { s_IAsyncEnumerable, source }); comp.VerifyDiagnostics( // (24,20): warning CS8600: Converting null literal or possible null value to non-nullable type. @@ -140065,15 +140237,22 @@ class B1 : A1 } class B2 : A2 { - public override void F1([DisallowNull] T t) { } + public override void F1([DisallowNull] T t) { } // 1 public override void F2([DisallowNull] T t) { } public override void F3([DisallowNull] T t) { } public override void F4([DisallowNull] T t) { } public override void F5([DisallowNull] T t) { } - public override void F6([DisallowNull] T t) { } + public override void F6([DisallowNull] T t) { } // 2 }"; comp = CreateCompilation(new[] { sourceB, DisallowNullAttributeDefinition, NotNullAttributeDefinition }, references: new[] { refA }); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (14,26): warning CS8765: Nullability of type of parameter 't' doesn't match overridden member (possibly because of nullability attributes). + // public override void F1([DisallowNull] T t) { } // 1 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F1").WithArguments("t").WithLocation(14, 26), + // (19,26): warning CS8765: Nullability of type of parameter 't' doesn't match overridden member (possibly because of nullability attributes). + // public override void F6([DisallowNull] T t) { } // 2 + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F6").WithArguments("t").WithLocation(19, 26) + ); } [Theory] @@ -140401,8 +140580,11 @@ class B : A public override void F3(out T? t) where T : default => throw null!; }"; comp = CreateCompilation(sourceB4, references: new[] { refA }); - // https://github.com/dotnet/roslyn/issues/49131: Should report warning for F2(). - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (5,26): warning CS8765: Nullability of type of parameter 't' doesn't match overridden member (possibly because of nullability attributes). + // public override void F2(out T? t) where T : default => throw null!; + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInParameterTypeOnOverride, "F2").WithArguments("t").WithLocation(5, 26) + ); } [Theory] @@ -142078,5 +142260,841 @@ static T GetValue2(Collection c, object key) // return s2; // 4 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s2").WithLocation(47, 20)); } + + [Theory, WorkItem(41368, "https://github.com/dotnet/roslyn/issues/41368")] + [CombinatorialData] + public void TypeSubstitution(bool useCompilationReference) + { + var sourceA = @" +#nullable enable +public class C +{ + public static TQ? FTQ(TQ? t) => throw null!; // T-question + public static T FT(T t) => throw null!; // plain-T + public static TC FTC(TC t) where TC : class => throw null!; // T-class +#nullable disable + public static TO FTO(TO t) => throw null!; // T-oblivious + public static TCO FTCO(TCO t) where TCO : class => throw null!; // T-class-oblivious +}"; + var comp = CreateCompilation(sourceA); + comp.VerifyDiagnostics(); + var refA = AsReference(comp, useCompilationReference); + + var sourceB2 = @" +#nullable enable +class CTQ +{ + void M() + { + var x0 = C.FTQ(default); + x0.ToString(); // 1 + + var x1 = C.FT(default); + x1.ToString(); // 2 + + C.FTC(default).ToString(); // illegal + + var x2 = C.FTO(default); + x2.ToString(); // 3 + + var x3 = C.FTCO(default); // illegal + x3.ToString(); + } +} + +class CT +{ + void M() + { + var x0 = C.FTQ(default); + x0.ToString(); // 4 + + var x1 = C.FT(default); // 5 + x1.ToString(); // 6 + + C.FTC(default).ToString(); // illegal + + var x2 = C.FTO(default); // 7 + x2.ToString(); // 8 + + C.FTCO(default).ToString(); // illegal + } +} +class CTC where TC : class +{ + void M() + { + var x0 = C.FTQ(default); + x0.ToString(); // 9 + + var x1 = C.FT(default); // 10 + x1.ToString(); + + var x2 = C.FTC(default); // 11 + x2.ToString(); + + var x3 = C.FTO(default); // 12 + x3.ToString(); + + var x4 = C.FTCO(default); // 13 + x4.ToString(); + } +} +class CTO +{ + void M() + { +#nullable disable + C.FTQ +#nullable enable + (default).ToString(); + + var x0 = +#nullable disable + C.FT +#nullable enable + (default); // 14 + x0.ToString(); // 15 + +#nullable disable + C.FTC // illegal +#nullable enable + (default).ToString(); + +#nullable disable + C.FTO +#nullable enable + (default).ToString(); + +#nullable disable + C.FTCO // illegal +#nullable enable + (default).ToString(); + } +} +class CTCO where TCO : class +{ + void M() + { + var x0 = +#nullable disable + C.FTQ +#nullable enable + (default); + x0.ToString(); // 16 + + var x1 = +#nullable disable + C.FT +#nullable enable + (default); // 17 + x1.ToString(); + + var x2 = +#nullable disable + C.FTC +#nullable enable + (default); // 18 + x2.ToString(); + +#nullable disable + C.FTO +#nullable enable + (default).ToString(); + +#nullable disable + C.FTCO +#nullable enable + (default).ToString(); + } +} +"; + comp = CreateCompilation(new[] { sourceB2 }, references: new[] { refA }); + comp.VerifyDiagnostics( + // (8,9): warning CS8602: Dereference of a possibly null reference. + // x0.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(8, 9), + // (11,9): warning CS8602: Dereference of a possibly null reference. + // x1.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(11, 9), + // (13,11): error CS0452: The type 'TQ' must be a reference type in order to use it as parameter 'TC' in the generic type or method 'C.FTC(TC)' + // C.FTC(default).ToString(); // illegal + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "FTC").WithArguments("C.FTC(TC)", "TC", "TQ").WithLocation(13, 11), + // (16,9): warning CS8602: Dereference of a possibly null reference. + // x2.ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(16, 9), + // (18,20): error CS0452: The type 'TQ' must be a reference type in order to use it as parameter 'TCO' in the generic type or method 'C.FTCO(TCO)' + // var x3 = C.FTCO(default); // illegal + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "FTCO").WithArguments("C.FTCO(TCO)", "TCO", "TQ").WithLocation(18, 20), + // (28,9): warning CS8602: Dereference of a possibly null reference. + // x0.ToString(); // 4 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(28, 9), + // (30,26): warning CS8604: Possible null reference argument for parameter 't' in 'T C.FT(T t)'. + // var x1 = C.FT(default); // 5 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default").WithArguments("t", "T C.FT(T t)").WithLocation(30, 26), + // (31,9): warning CS8602: Dereference of a possibly null reference. + // x1.ToString(); // 6 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(31, 9), + // (33,11): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'TC' in the generic type or method 'C.FTC(TC)' + // C.FTC(default).ToString(); // illegal + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "FTC").WithArguments("C.FTC(TC)", "TC", "T").WithLocation(33, 11), + // (35,27): warning CS8604: Possible null reference argument for parameter 't' in 'T C.FTO(T t)'. + // var x2 = C.FTO(default); // 7 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default").WithArguments("t", "T C.FTO(T t)").WithLocation(35, 27), + // (36,9): warning CS8602: Dereference of a possibly null reference. + // x2.ToString(); // 8 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(36, 9), + // (38,11): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'TCO' in the generic type or method 'C.FTCO(TCO)' + // C.FTCO(default).ToString(); // illegal + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "FTCO").WithArguments("C.FTCO(TCO)", "TCO", "T").WithLocation(38, 11), + // (46,9): warning CS8602: Dereference of a possibly null reference. + // x0.ToString(); // 9 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(46, 9), + // (48,27): warning CS8625: Cannot convert null literal to non-nullable reference type. + // var x1 = C.FT(default); // 10 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(48, 27), + // (51,28): warning CS8625: Cannot convert null literal to non-nullable reference type. + // var x2 = C.FTC(default); // 11 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(51, 28), + // (54,28): warning CS8625: Cannot convert null literal to non-nullable reference type. + // var x3 = C.FTO(default); // 12 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(54, 28), + // (57,29): warning CS8625: Cannot convert null literal to non-nullable reference type. + // var x4 = C.FTCO(default); // 13 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(57, 29), + // (74,18): warning CS8604: Possible null reference argument for parameter 't' in 'TO C.FT(TO t)'. + // (default); // 14 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default").WithArguments("t", "TO C.FT(TO t)").WithLocation(74, 18), + // (75,9): warning CS8602: Dereference of a possibly null reference. + // x0.ToString(); // 15 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(75, 9), + // (78,11): error CS0452: The type 'TO' must be a reference type in order to use it as parameter 'TC' in the generic type or method 'C.FTC(TC)' + // C.FTC // illegal + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "FTC").WithArguments("C.FTC(TC)", "TC", "TO").WithLocation(78, 11), + // (88,11): error CS0452: The type 'TO' must be a reference type in order to use it as parameter 'TCO' in the generic type or method 'C.FTCO(TCO)' + // C.FTCO // illegal + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "FTCO").WithArguments("C.FTCO(TCO)", "TCO", "TO").WithLocation(88, 11), + // (102,9): warning CS8602: Dereference of a possibly null reference. + // x0.ToString(); // 16 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x0").WithLocation(102, 9), + // (108,18): warning CS8625: Cannot convert null literal to non-nullable reference type. + // (default); // 17 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(108, 18), + // (115,18): warning CS8625: Cannot convert null literal to non-nullable reference type. + // (default); // 18 + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "default").WithLocation(115, 18) + ); + } + + [Fact] + public void AmbigMember_DynamicDifferences() + { + var src = @" +interface I { T Item { get; } } + +interface I2 : I { } + +interface I3 : I, I2 { } + +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (6,11): error CS8779: 'I' is already listed in the interface list on type 'I3' as 'I'. + // interface I3 : I, I2 { } + Diagnostic(ErrorCode.ERR_DuplicateInterfaceWithDifferencesInBaseList, "I3").WithArguments("I", "I", "I3").WithLocation(6, 11), + // (6,16): error CS1966: 'I3': cannot implement a dynamic interface 'I' + // interface I3 : I, I2 { } + Diagnostic(ErrorCode.ERR_DeriveFromConstructedDynamic, "I").WithArguments("I3", "I").WithLocation(6, 16), + // (12,15): error CS0229: Ambiguity between 'I.Item' and 'I.Item' + // _ = i.Item; + Diagnostic(ErrorCode.ERR_AmbigMember, "Item").WithArguments("I.Item", "I.Item").WithLocation(12, 15) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I", "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_TupleDifferences() + { + var src = @" +interface I { T Item { get; } } + +interface I2 : I { } + +interface I3 : I<(int a, int b)>, I2<(int notA, int notB)> { } + +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (6,11): error CS8140: 'I<(int notA, int notB)>' is already listed in the interface list on type 'I3' with different tuple element names, as 'I<(int a, int b)>'. + // interface I3 : I<(int a, int b)>, I2<(int notA, int notB)> { } + Diagnostic(ErrorCode.ERR_DuplicateInterfaceWithTupleNamesInBaseList, "I3").WithArguments("I<(int notA, int notB)>", "I<(int a, int b)>", "I3").WithLocation(6, 11), + // (12,15): error CS0229: Ambiguity between 'I<(int a, int b)>.Item' and 'I<(int notA, int notB)>.Item' + // _ = i.Item; + Diagnostic(ErrorCode.ERR_AmbigMember, "Item").WithArguments("I<(int a, int b)>.Item", "I<(int notA, int notB)>.Item").WithLocation(12, 15) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I<(int a, int b)>", "I2<(int notA, int notB)>" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I<(int a, int b)>", "I2<(int notA, int notB)>", "I<(int notA, int notB)>" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_TupleAndNullabilityDifferences() + { + var src = @" +#nullable disable +interface I { T Item { get; } } + +#nullable enable +interface I2 : I { } + +#nullable disable +interface I3 : I<(object a, object b)>, I2<(object notA, object notB)> { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (9,11): error CS8140: 'I<(object notA, object notB)>' is already listed in the interface list on type 'I3' with different tuple element names, as 'I<(object a, object b)>'. + // interface I3 : I<(object a, object b)>, I2<(object notA, object notB)> { } + Diagnostic(ErrorCode.ERR_DuplicateInterfaceWithTupleNamesInBaseList, "I3").WithArguments("I<(object notA, object notB)>", "I<(object a, object b)>", "I3").WithLocation(9, 11), + // (16,15): error CS0229: Ambiguity between 'I<(object a, object b)>.Item' and 'I<(object notA, object notB)>.Item' + // _ = i.Item; + Diagnostic(ErrorCode.ERR_AmbigMember, "Item").WithArguments("I<(object a, object b)>.Item", "I<(object notA, object notB)>.Item").WithLocation(16, 15) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I<(object a, object b)>", "I2<(object notA, object notB)>" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I<(object a, object b)>", "I2<(object notA, object notB)>", "I<(object notA, object notB)>" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_NoDifference() + { + var src = @" +interface I { T Item { get; } } + +interface I2 : I { } + +interface I3 : I, I2 { } + +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNonnullableAndOblivious_WithoutConstraint() + { + var src = @" +#nullable disable +interface I { T Item { get; set; } } + +#nullable enable +interface I2 : I { } + +#nullable disable +interface I3 : I, I2 { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + i.Item = null; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I" , "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNonnullableAndOblivious_WithoutConstraint_ReverseOrder() + { + var src = @" +#nullable disable +interface I { T Item { get; set; } } + +#nullable enable +interface I2 : I { } + +#nullable disable +interface I3 : I2, I { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + i.Item = null; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (17,18): warning CS8625: Cannot convert null literal to non-nullable reference type. + // i.Item = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(17, 18) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I2", "I" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I2", "I", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNonnullableAndOblivious_WithConstraint() + { + var src = @" +#nullable disable +interface I where T : class { T Item { get; set; } } + +#nullable enable +interface I2 : I where T : class { } + +#nullable disable +interface I3 : I, I2 { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + i.Item = null; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I", "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNonnullableAndOblivious_WithConstraint_ReverseOrder() + { + var src = @" +#nullable disable +interface I where T : class { T Item { get; set; } } + +#nullable enable +interface I2 : I where T : class { } + +#nullable disable +interface I3 : I2, I { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + i.Item = null; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (17,18): warning CS8625: Cannot convert null literal to non-nullable reference type. + // i.Item = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(17, 18) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I2", "I" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I2", "I", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNullableAndOblivious_WithConstraint() + { + var src = @" +#nullable disable +interface I where T : class { T Item { get; } } + +#nullable enable +interface I2 : I where T : class { } + +interface I3 : I, +#nullable disable + I2 { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (8,11): warning CS8645: 'I' is already listed in the interface list on type 'I3' with different nullability of reference types. + // interface I3 : I, + Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "I3").WithArguments("I", "I3").WithLocation(8, 11) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I", "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNullableAndOblivious_WithoutConstraint() + { + var src = @" +#nullable disable +interface I { T Item { get; } } + +#nullable enable +interface I2 : I { } + +interface I3 : I, +#nullable disable + I2 { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (8,11): warning CS8645: 'I' is already listed in the interface list on type 'I3' with different nullability of reference types. + // interface I3 : I, + Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "I3").WithArguments("I", "I3").WithLocation(8, 11) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I", "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] + public void AmbigMember_DifferenceBetweenNullableAndNonnullable() + { + var src = @" +#nullable disable +interface I where T : class { T Item { get; } } + +#nullable enable +interface I2 : I where T : class { } + +interface I3 : I, I2 { } + +#nullable enable +public class C +{ + void M(I3 i) + { + _ = i.Item; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (8,11): warning CS8645: 'I' is already listed in the interface list on type 'I3' with different nullability of reference types. + // interface I3 : I, I2 { } + Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "I3").WithArguments("I", "I3").WithLocation(8, 11) + ); + var i3 = comp.GetTypeByMetadataName("I3"); + AssertEx.Equal(new string[] { "I", "I2" }, + i3.Interfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + AssertEx.Equal(new string[] { "I", "I2", "I" }, + i3.AllInterfaces().ToTestDisplayStrings(TypeWithAnnotations.TestDisplayFormat)); + } + + [Fact] // TODO2 bug number + public void DefaultParameterValue() + { + var src = @" +#nullable enable + +C one = new(); +C other = new(); + +_ = one.SequenceEqual(other); // Note: the default parameter value contributes type `C` +_ = one.SequenceEqual(other, comparer: null); + +public interface IIn { } + +static class Extension +{ + public static bool SequenceEqual(this C one, C other, IIn? comparer = null) where TDerived : TBase + => throw null!; +} + +public class C +{ +} +"; + var comp = CreateCompilation(src, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (7,5): warning CS8631: The type 'string?' cannot be used as type parameter 'TDerived' in the generic type or method 'Extension.SequenceEqual(C, C, IIn?)'. Nullability of type argument 'string?' doesn't match constraint type 'string'. + // _ = one.SequenceEqual(other); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "one.SequenceEqual").WithArguments("Extension.SequenceEqual(C, C, IIn?)", "string", "TDerived", "string?").WithLocation(7, 5), + // (7,5): warning CS8620: Argument of type 'C' cannot be used for parameter 'one' of type 'C' in 'bool Extension.SequenceEqual(C one, C other, IIn? comparer = null)' due to differences in the nullability of reference types. + // _ = one.SequenceEqual(other); + Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "one").WithArguments("C", "C", "one", "bool Extension.SequenceEqual(C one, C other, IIn? comparer = null)").WithLocation(7, 5) + ); + } + + [Fact] // TODO2 bug number + public void Implement() + { + var src = @" +#nullable enable +public interface I +{ + T M(); +} + +#nullable disable +public abstract class Base : I +{ + public abstract T M(); +} + +#nullable enable +public class Derived : Base, I +{ + public override T? M() where T : default + => throw null!; +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (17,24): warning CS8766: Nullability of reference types in return type of 'T? Derived.M()' doesn't match implicitly implemented member 'T I.M()' (possibly because of nullability attributes). + // public override T? M() where T : default + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnImplicitImplementation, "M").WithArguments("T? Derived.M()", "T I.M()").WithLocation(17, 24) + ); + } + + [Fact] // TODO2 bug number + public void Implement_WithClassConstraint() + { + var src = @" +#nullable enable +public interface I +{ + T M() where T : class; +} + +#nullable disable +public abstract class Base : I +{ + public abstract T M() where T : class; +} + +#nullable enable +public class Derived : Base, I +{ + public override T? M() where T : class + => throw null!; +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (17,24): warning CS8766: Nullability of reference types in return type of 'T? Derived.M()' doesn't match implicitly implemented member 'T I.M()' (possibly because of nullability attributes). + // public override T? M() where T : class + Diagnostic(ErrorCode.WRN_TopLevelNullabilityMismatchInReturnTypeOnImplicitImplementation, "M").WithArguments("T? Derived.M()", "T I.M()").WithLocation(17, 24) + ); + } + + [Fact] + public void IgnoredNullability_ConditionalWithThis() + { + var src = @" +#nullable enable + +internal class C +{ + public C M(bool b) + { + if (b) + return b ? this : new C(); + else + return b ? new C() : this; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + // TODO2 verify types of expressions + } + + [Fact] + public void IgnoredNullability_ImplicitlyTypedArrayWithThis() + { + var src = @" +#nullable enable + +internal class C +{ + public C[] M(bool b) + { + if (b) + return new[] { this, new C() }; + else + return new[] { new C(), this }; + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + // TODO2 verify types of expressions + } + + [Fact] + public void IgnoredNullability_ImplicitlyTypedArrayWithThis_DifferentNullability() + { + var src = @" +#nullable enable + +internal class C +{ + public void M(bool b) + { + _ = b ? this : new C(); + } +} +"; + var comp = CreateCompilation(src); + // TODO2 missing warning (existing bug) + comp.VerifyDiagnostics(); + } + + [Fact] + public void CopyTypeModifiers_ImplicitContainingType() + { + var src = @" +#nullable enable + +var c = new C(); +c.Property.Property2 = null; + +public interface I +{ + T Property { get; set; } +} +public class C : I.Nested> +{ + public Nested Property { get; set; } // implicitly means C.Nested + public class Nested + { + public U Property2 { get; set; } + } +} +"; + var comp = CreateCompilation(src, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (5,24): warning CS8625: Cannot convert null literal to non-nullable reference type. + // c.Property.Property2 = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(5, 24), + // (13,19): warning CS8618: Non-nullable property 'Property' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. + // public Nested Property { get; set; } // implicitly means C.Nested + Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Property").WithArguments("property", "Property").WithLocation(13, 19), + // (16,18): warning CS8618: Non-nullable property 'Property2' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. + // public U Property2 { get; set; } + Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Property2").WithArguments("property", "Property2").WithLocation(16, 18) + ); + } + + [Fact] + public void CopyTypeModifiers_ExplicitContainingType() + { + var src = @" +#nullable enable + +var c = new C(); +c.Property.Property2 = null; + +public interface I +{ + public T Property { get; set; } +} +public class C : I.Nested> +{ + public C.Nested Property { get; set; } + public class Nested + { + public U Property2 { get; set; } + } +} +"; + var comp = CreateCompilation(src, options: TestOptions.DebugExe); + comp.VerifyDiagnostics( + // (5,24): warning CS8625: Cannot convert null literal to non-nullable reference type. + // c.Property.Property2 = null; + Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(5, 24), + // (13,24): warning CS8618: Non-nullable property 'Property' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. + // public C.Nested Property { get; set; } + Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Property").WithArguments("property", "Property").WithLocation(13, 24), + // (16,18): warning CS8618: Non-nullable property 'Property2' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. + // public U Property2 { get; set; } + Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Property2").WithArguments("property", "Property2").WithLocation(16, 18) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs index ff711d95762f..e1aa2782edba 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs @@ -57708,13 +57708,7 @@ interface D : A.E compilation1.VerifyDiagnostics( // (4,11): warning CS8645: 'C' is already listed in the interface list on type 'A' with different nullability of reference types. // interface A : B, C - Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "A").WithArguments("C", "A").WithLocation(4, 11), - // (18,17): error CS0104: 'E' is an ambiguous reference between 'C.E' and 'C.E' - // interface D : A.E - Diagnostic(ErrorCode.ERR_AmbigContext, "E").WithArguments("E", "C.E", "C.E").WithLocation(18, 17), - // (20,7): error CS0104: 'E' is an ambiguous reference between 'C.E' and 'C.E' - // A.E Test(); - Diagnostic(ErrorCode.ERR_AmbigContext, "E").WithArguments("E", "C.E", "C.E").WithLocation(20, 7) + Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "A").WithArguments("C", "A").WithLocation(4, 11) ); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs index 13da3ba1494c..f2eb041bbdb5 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/NullablePublicAPITests.cs @@ -773,7 +773,7 @@ public interface I PublicNullableAnnotation.Annotated); } - [Fact] + [Fact(Skip = "TODO2")] [WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")] public void Constraints() { diff --git a/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs b/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs index ef9ebdb34b54..e8e31937c8a5 100644 --- a/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs @@ -188,8 +188,7 @@ public static void AddIfNotNull(this ArrayBuilder builder, T? value) } } -#nullable disable - public static void FreeAll(this ArrayBuilder builder, Func> getNested) + public static void FreeAll(this ArrayBuilder builder, Func?> getNested) { foreach (var item in builder) { @@ -197,6 +196,5 @@ public static void FreeAll(this ArrayBuilder builder, Func ISymbol OriginalDefinition { get; } void Accept(SymbolVisitor visitor); - TResult Accept(SymbolVisitor visitor); + TResult? Accept(SymbolVisitor visitor); /// /// Returns the Documentation Comment ID for the symbol, or null if the symbol doesn't diff --git a/src/Compilers/Test/Utilities/CSharp/SymbolUtilities.cs b/src/Compilers/Test/Utilities/CSharp/SymbolUtilities.cs index 3eec14fa1e4c..1fc962e21b13 100644 --- a/src/Compilers/Test/Utilities/CSharp/SymbolUtilities.cs +++ b/src/Compilers/Test/Utilities/CSharp/SymbolUtilities.cs @@ -120,9 +120,10 @@ public static string[] ToTestDisplayStrings(this IEnumerable symbols) return symbols.Select(s => s.ToTestDisplayString()).ToArray(); } - public static string[] ToTestDisplayStrings(this IEnumerable symbols) + public static string[] ToTestDisplayStrings(this IEnumerable symbols, SymbolDisplayFormat format = null) { - return symbols.Select(s => s.ToTestDisplayString()).ToArray(); + format ??= SymbolDisplayFormat.TestFormat; + return symbols.Select(s => s.ToDisplayString(format)).ToArray(); } public static string ToTestDisplayString(this ISymbol symbol, bool includeNonNullable) diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs index e1c68dc154a1..bb29a812ed40 100644 --- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs +++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs @@ -3088,7 +3088,7 @@ private void ReportLambdaAndClosureRudeEdits( { foreach (var newQueryClause in from clause in lazyNewErroneousClauses orderby clause.SpanStart - group clause by GetContainingQueryExpression(clause) into clausesByQuery + group clause by GetContainingQueryExpression(clause)! into clausesByQuery // TODO2 select clausesByQuery.First()) { diagnostics.Add(new RudeEditDiagnostic( diff --git a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs index 0dbc17177766..5abf70b91589 100644 --- a/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs +++ b/src/Features/Core/Portable/SolutionCrawler/SolutionCrawlerLogger.cs @@ -57,7 +57,7 @@ public static void LogRegistration(int correlationId, Workspace workspace) Logger.Log(FunctionId.WorkCoordinatorRegistrationService_Register, KeyValueLogMessage.Create(m => { m[Id] = correlationId; - m[Kind] = workspace.Kind; + m[Kind] = workspace.Kind!; // TODO2 })); } @@ -79,7 +79,7 @@ public static void LogReanalyze( Logger.Log(FunctionId.WorkCoordinatorRegistrationService_Reanalyze, KeyValueLogMessage.Create(m => { m[Id] = correlationId; - m[Analyzer] = analyzer.ToString(); + m[Analyzer] = analyzer.ToString()!; // TODO2 m[DocumentCount] = documentCount; m[HighPriority] = highPriority; m[Languages] = languages; @@ -131,7 +131,7 @@ private static void LogAnalyzersWorker( Logger.Log(analyzerId, KeyValueLogMessage.Create(m => { m[Id] = correlationId; - m[Analyzer] = analyzer.ToString(); + m[Analyzer] = analyzer.ToString()!; // TODO2 })); } } diff --git a/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllLogger.cs b/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllLogger.cs index 979ead7be970..86382806f208 100644 --- a/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllLogger.cs +++ b/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllLogger.cs @@ -40,6 +40,8 @@ internal static class FixAllLogger public static void LogState(FixAllState fixAllState, bool isInternalCodeFixProvider) { + // TODO2 using the KeyValueLogMessage API is painful +#nullable disable Logger.Log(FunctionId.CodeFixes_FixAllOccurrencesContext, KeyValueLogMessage.Create(m => { m[CorrelationId] = fixAllState.CorrelationId; @@ -69,6 +71,7 @@ public static void LogState(FixAllState fixAllState, bool isInternalCodeFixProvi break; } })); +#nullable enable } public static void LogComputationResult(int correlationId, bool completed, bool timedOut = false) diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationSymbol.cs index d0084ef2d650..7d71b26bc459 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationSymbol.cs @@ -173,7 +173,9 @@ public ISymbol OriginalDefinition public abstract void Accept(SymbolVisitor visitor); - public abstract TResult Accept(SymbolVisitor visitor); +#nullable enable + public abstract TResult? Accept(SymbolVisitor visitor); +#nullable disable public string GetDocumentationCommentId() => null; diff --git a/src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_BulkPopulateIds.cs b/src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_BulkPopulateIds.cs index a4690326dda1..34ae126b969a 100644 --- a/src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_BulkPopulateIds.cs +++ b/src/Workspaces/Core/Portable/Storage/SQLite/v1/SQLitePersistentStorage_BulkPopulateIds.cs @@ -207,7 +207,10 @@ string GetDocumentIdString(Document document) { // We should always be able to index directly into these maps. This function is only // ever called after we called AddIndividualProjectAndDocumentComponentIds. +#nullable disable + // TODO2 var documentPathId = _stringToIdMap[document.FilePath]; +#nullable enable var documentNameId = _stringToIdMap[document.Name]; var documentIdString = SQLitePersistentStorage.GetDocumentIdString( diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.ExpressionSyntaxGeneratorVisitor.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.ExpressionSyntaxGeneratorVisitor.cs index 1ab5c3ea5ec6..bc0112cf65b5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.ExpressionSyntaxGeneratorVisitor.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.ExpressionSyntaxGeneratorVisitor.cs @@ -19,7 +19,7 @@ private ExpressionSyntaxGeneratorVisitor() } public override ExpressionSyntax DefaultVisit(ISymbol symbol) - => symbol.Accept(TypeSyntaxGeneratorVisitor.Create()); + => symbol.Accept(TypeSyntaxGeneratorVisitor.Create())!; // TODO2 private static TExpressionSyntax AddInformationTo(TExpressionSyntax syntax, ISymbol symbol) where TExpressionSyntax : ExpressionSyntax @@ -48,7 +48,7 @@ public override ExpressionSyntax VisitNamedType(INamedTypeSymbol symbol) } else { - var container = symbol.ContainingType.Accept(this); + var container = symbol.ContainingType.Accept(this)!; // TODO2 return CreateMemberAccessExpression(symbol, container, simpleNameSyntax); } } @@ -66,7 +66,7 @@ public override ExpressionSyntax VisitNamedType(INamedTypeSymbol symbol) } else { - var container = symbol.ContainingNamespace.Accept(this); + var container = symbol.ContainingNamespace.Accept(this)!; // TODO2 return CreateMemberAccessExpression(symbol, container, simpleNameSyntax); } } @@ -91,7 +91,7 @@ public override ExpressionSyntax VisitNamespace(INamespaceSymbol symbol) } else { - var container = symbol.ContainingNamespace.Accept(this); + var container = symbol.ContainingNamespace.Accept(this)!; // TODO2 return CreateMemberAccessExpression(symbol, container, syntax); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs index 6fb64a1a79f5..4e99984aef87 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs @@ -293,7 +293,7 @@ public override TypeSyntax VisitNamedType(INamedTypeSymbol symbol) } else { - var container = symbol.ContainingNamespace.Accept(this); + var container = symbol.ContainingNamespace.Accept(this)!; // TODO2 typeSyntax = AddInformationTo(SyntaxFactory.QualifiedName( (NameSyntax)container, simpleNameSyntax), symbol); @@ -323,7 +323,7 @@ public override TypeSyntax VisitNamespace(INamespaceSymbol symbol) } else { - var container = symbol.ContainingNamespace.Accept(this); + var container = symbol.ContainingNamespace.Accept(this)!; // TODO2 return AddInformationTo(SyntaxFactory.QualifiedName( (NameSyntax)container, syntax), symbol); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs index 7d4da3afe498..4c38233f2f0c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.cs @@ -22,7 +22,7 @@ internal static partial class ITypeSymbolExtensions public static ExpressionSyntax GenerateExpressionSyntax( this ITypeSymbol typeSymbol) { - return typeSymbol.Accept(ExpressionSyntaxGeneratorVisitor.Instance).WithAdditionalAnnotations(Simplifier.Annotation); + return typeSymbol.Accept(ExpressionSyntaxGeneratorVisitor.Instance)!.WithAdditionalAnnotations(Simplifier.Annotation)!; // TODO2 } public static NameSyntax GenerateNameSyntax( @@ -48,8 +48,8 @@ private static TypeSyntax GenerateTypeSyntax( return SyntaxFactory.IdentifierName("var"); } - var syntax = symbol.Accept(TypeSyntaxGeneratorVisitor.Create(nameSyntax)) - .WithAdditionalAnnotations(Simplifier.Annotation); + var syntax = symbol.Accept(TypeSyntaxGeneratorVisitor.Create(nameSyntax))! + .WithAdditionalAnnotations(Simplifier.Annotation)!; // TODO2 if (!allowVar) {