diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs index c7e3ef85a9f581..b09bb83a5a6870 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs @@ -385,12 +385,14 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, ILi for (int i = 0, offset = 0; i < genericArguments.Length; i++) { - if (!genericArguments[i].IsValueType) + Type t = Nullable.GetUnderlyingType(genericArguments[i]) ?? genericArguments[i]; + + if (!t.IsValueType || t.IsGenericType) { offset++; } - genericArgumentsState[i] = GetNullabilityInfo(memberInfo, genericArguments[i], customAttributes, offset); + genericArgumentsState[i] = GetNullabilityInfo(memberInfo, genericArguments[i], customAttributes, index + offset); } } @@ -480,7 +482,7 @@ private void CheckGenericParameters(NullabilityInfo nullability, MemberInfo meta { NullabilityState state = nullability.ReadState; - if (!ParseNullableState(metaType.GetCustomAttributesData(), 0, ref state)) + if (state == NullabilityState.NotNull && !ParseNullableState(metaType.GetCustomAttributesData(), 0, ref state)) { state = GetNullableContext(metaType); } diff --git a/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs index a1ec3c648137c4..f444a5624c6bb6 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs @@ -33,7 +33,7 @@ public static IEnumerable FieldTestData() yield return new object[] { "FieldAllowNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; - yield return new object[] { "FieldMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; + yield return new object[] { "FieldMaybeNull2", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "FieldNotNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; } @@ -121,7 +121,7 @@ public static IEnumerable ArrayPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(ArrayPropertyTestData))] public void ArrayPropertyTest(string propertyName, NullabilityState elementState, NullabilityState propertyState) { @@ -143,7 +143,7 @@ public static IEnumerable GenericArrayPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(GenericArrayPropertyTestData))] public void GenericArrayPropertyTest(string propertyName, NullabilityState elementState, NullabilityState propertyState) { @@ -167,7 +167,7 @@ public static IEnumerable JaggedArrayPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(JaggedArrayPropertyTestData))] public void JaggedArrayPropertyTest(string propertyName, NullabilityState innermodtElementState, NullabilityState elementState, NullabilityState propertyState) { @@ -192,7 +192,7 @@ public static IEnumerable TuplePropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(TuplePropertyTestData))] public void TuplePropertyTest(string propertyName, NullabilityState genericParam1, NullabilityState genericParam2, NullabilityState genericParam3, NullabilityState propertyState) { @@ -217,7 +217,7 @@ public static IEnumerable GenericTuplePropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(GenericTuplePropertyTestData))] public void GenericTuplePropertyTest(string propertyName, NullabilityState genericParam1, NullabilityState genericParam2, NullabilityState genericParam3, NullabilityState propertyState) { @@ -243,7 +243,7 @@ public static IEnumerable DictionaryPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(DictionaryPropertyTestData))] public void DictionaryPropertyTest(string propertyName, NullabilityState keyState, NullabilityState valueElement, NullabilityState valueState, NullabilityState propertyState) { @@ -269,7 +269,7 @@ public static IEnumerable GenericDictionaryPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(GenericDictionaryPropertyTestData))] public void GenericDictionaryPropertyTest(string propertyName, NullabilityState keyState, NullabilityState valueElement, NullabilityState valueState, NullabilityState propertyState) { @@ -433,16 +433,16 @@ public void GenericFieldNullableValueTypeTest(string fieldName, NullabilityState Assert.Equal(type, nullability.Type); } - public static IEnumerable GenericNotnullConstraintTestData() + public static IEnumerable GenericNotnullConstraintFieldsTestData() { - yield return new object[] { "FieldNullable", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; + yield return new object[] { "FieldNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldUnknown", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; yield return new object[] { "FieldNullableEnabled", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; } [Theory] - [MemberData(nameof(GenericNotnullConstraintTestData))] - public void GenericNotNullConstraintTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) + [MemberData(nameof(GenericNotnullConstraintFieldsTestData))] + public void GenericNotNullConstraintFieldsTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) { FieldInfo field = typeof(GenericTestConstrainedNotNull).GetField(fieldName, flags)!; NullabilityInfo nullability = nullabilityContext.Create(field); @@ -451,7 +451,25 @@ public void GenericNotNullConstraintTest(string fieldName, NullabilityState read Assert.Equal(type, nullability.Type); } - public static IEnumerable GenericStructConstraintTestData() + public static IEnumerable GenericNotnullConstraintPropertiesTestData() + { + yield return new object[] { "PropertyNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(string) }; + yield return new object[] { "PropertyUnknown", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyNullableEnabled", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; + } + + [Theory] + [MemberData(nameof(GenericNotnullConstraintPropertiesTestData))] + public void GenericNotNullConstraintPropertiesTest(string propertyName, NullabilityState readState, NullabilityState writeState, Type type) + { + PropertyInfo property = typeof(GenericTestConstrainedNotNull).GetProperty(propertyName, flags)!; + NullabilityInfo nullability = nullabilityContext.Create(property); + Assert.Equal(readState, nullability.ReadState); + Assert.Equal(writeState, nullability.WriteState); + Assert.Equal(type, nullability.Type); + } + + public static IEnumerable GenericStructConstraintFieldsTestData() { yield return new object[] { "FieldNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(int?) }; yield return new object[] { "FieldUnknown", NullabilityState.NotNull, NullabilityState.NotNull, typeof(int) }; @@ -459,8 +477,8 @@ public static IEnumerable GenericStructConstraintTestData() } [Theory] - [MemberData(nameof(GenericStructConstraintTestData))] - public void GenericStructConstraintTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) + [MemberData(nameof(GenericStructConstraintFieldsTestData))] + public void GenericStructConstraintFieldsTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) { FieldInfo field = typeof(GenericTestConstrainedStruct).GetField(fieldName, flags)!; NullabilityInfo nullability = nullabilityContext.Create(field); @@ -469,6 +487,24 @@ public void GenericStructConstraintTest(string fieldName, NullabilityState readS Assert.Equal(type, nullability.Type); } + public static IEnumerable GenericStructConstraintPropertiesTestData() + { + yield return new object[] { "PropertyNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(int?) }; + yield return new object[] { "PropertyUnknown", NullabilityState.NotNull, NullabilityState.NotNull, typeof(int) }; + yield return new object[] { "PropertyNullableEnabled", NullabilityState.NotNull, NullabilityState.NotNull, typeof(int) }; + } + + [Theory] + [MemberData(nameof(GenericStructConstraintPropertiesTestData))] + public void GenericStructConstraintPropertiesTest(string propertyName, NullabilityState readState, NullabilityState writeState, Type type) + { + PropertyInfo property = typeof(GenericTestConstrainedStruct).GetProperty(propertyName, flags)!; + NullabilityInfo nullability = nullabilityContext.Create(property); + Assert.Equal(readState, nullability.ReadState); + Assert.Equal(writeState, nullability.WriteState); + Assert.Equal(type, nullability.Type); + } + [Fact] [SkipOnMono("Nullability attributes trimmed on Mono")] public void GenericListTest() @@ -544,7 +580,7 @@ public static IEnumerable MethodReturnParameterTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodReturnParameterTestData))] public void MethodReturnParameterTest(string methodName, NullabilityState elementState, NullabilityState readState) { @@ -557,6 +593,31 @@ public void MethodReturnParameterTest(string methodName, NullabilityState elemen Assert.Empty(nullability.GenericTypeArguments); } + public static IEnumerable MethodReturnsTupleTestData() + { + // public Tuple? MethodReturnsTupleNullNonNull() => null; + yield return new object[] { "MethodReturnsTupleNullNonNull", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + // public Tuple MethodReturnsTupleNullNonNot() => null! + yield return new object[] { "MethodReturnsTupleNullNonNot", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull }; + // public (int?, string)? MethodReturnsValueTupleNullNonNull() => null; + yield return new object[] { "MethodReturnsValueTupleNullNonNull", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + // public (string?, string) MethodReturnsValueTupleNullNonNon() => (null, string.Empty); + yield return new object[] { "MethodReturnsValueTupleNullNonNon", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull }; + } + + [Theory] + [SkipOnMono("Nullability attributes trimmed on Mono")] + [MemberData(nameof(MethodReturnsTupleTestData))] + public void MethodReturnsTupleTest(string methodName, NullabilityState param1, NullabilityState param2, NullabilityState readState) + { + MethodInfo method = testType.GetMethod(methodName, flags)!; + NullabilityInfo nullability = nullabilityContext.Create(method.ReturnParameter); + Assert.Equal(readState, nullability.ReadState); + Assert.Null(nullability.ElementType); + Assert.Equal(param1, nullability.GenericTypeArguments[0].ReadState); + Assert.Equal(param2, nullability.GenericTypeArguments[1].ReadState); + } + public static IEnumerable MethodGenericReturnParameterTestData() { yield return new object[] { "MethodReturnsUnknown", NullabilityState.Unknown, NullabilityState.Unknown }; @@ -569,7 +630,7 @@ public static IEnumerable MethodGenericReturnParameterTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodGenericReturnParameterTestData))] public void MethodGenericReturnParameterTest(string methodName, NullabilityState readState, NullabilityState elementState) { @@ -592,7 +653,7 @@ public static IEnumerable MethodParametersTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodParametersTestData))] public void MethodParametersTest(string methodName, NullabilityState stringState, NullabilityState dictKey, NullabilityState dictValueElement, NullabilityState dictValue, NullabilityState dictionaryState) { @@ -616,7 +677,7 @@ public static IEnumerable MethodGenericParametersTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodGenericParametersTestData))] public void MethodGenericParametersTest(string methodName, NullabilityState param1State, NullabilityState dictKey, NullabilityState dictValue, NullabilityState dictionaryState) { @@ -705,6 +766,8 @@ public void NullablePublicOnlyOtherTypesTest() public static IEnumerable DifferentContextTestData() { yield return new object[] { "PropertyDisabled", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyDisabledAllowNull", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyDisabledMaybeNull", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; yield return new object[] { "PropertyEnabledAllowNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyEnabledNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyEnabledMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; @@ -766,15 +829,15 @@ public void AttributedParametersTest() Assert.Equal(NullabilityState.Nullable, notNullIfNotNull.WriteState); Assert.Equal(NullabilityState.Nullable, nullabilityContext.Create(allowNullParameter[1]).ReadState); - // [return: NotNullIfNotNull("nullable")] public string? NullablNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) - ParameterInfo[] nullablNotNullIfNotNullReturn = type.GetMethod("NullablNotNullIfNotNullReturn", flags)!.GetParameters(); - NullabilityInfo returnNotNullIfNotNull = nullabilityContext.Create(type.GetMethod("NullablNotNullIfNotNullReturn", flags)!.ReturnParameter); - NullabilityInfo readNotNull = nullabilityContext.Create(nullablNotNullIfNotNullReturn[1]); + // [return: NotNullIfNotNull("nullable")] public string? NullableNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) + ParameterInfo[] nullableNotNullIfNotNullReturn = type.GetMethod("NullableNotNullIfNotNullReturn", flags)!.GetParameters(); + NullabilityInfo returnNotNullIfNotNull = nullabilityContext.Create(type.GetMethod("NullableNotNullIfNotNullReturn", flags)!.ReturnParameter); + NullabilityInfo readNotNull = nullabilityContext.Create(nullableNotNullIfNotNullReturn[1]); Assert.Equal(NullabilityState.Nullable, returnNotNullIfNotNull.ReadState); Assert.Equal(NullabilityState.Nullable, returnNotNullIfNotNull.WriteState); Assert.Equal(NullabilityState.NotNull, readNotNull.ReadState); Assert.Equal(NullabilityState.Nullable, readNotNull.WriteState); - Assert.Equal(NullabilityState.Nullable, nullabilityContext.Create(nullablNotNullIfNotNullReturn[0]).ReadState); + Assert.Equal(NullabilityState.Nullable, nullabilityContext.Create(nullableNotNullIfNotNullReturn[0]).ReadState); // public bool TryGetOutParameters(string id, [NotNullWhen(true)] out string? value, [MaybeNullWhen(false)] out string value2) ParameterInfo[] tryGetOutParameters = type.GetMethod("TryGetOutParameters", flags)!.GetParameters(); @@ -787,6 +850,51 @@ public void AttributedParametersTest() Assert.Equal(NullabilityState.NotNull, nullabilityContext.Create(tryGetOutParameters[0]).ReadState); } + public static IEnumerable NestedGenericsReturnParameterData() + { + // public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; + yield return new object[] { "MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon", + NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable?>? MethodReturnsEnumerableNullTupleNullNonNullValueTupleNullNonNull() => null!; + yield return new object[] { "MethodReturnsEnumerableNullTupleNullNonNullValueTupleNullNonNull", + NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull }; + + // public IEnumerable, int>?> MethodReturnsEnumerableNonTupleNonNonNullTupleNonNullNon() => null!; + yield return new object[] { "MethodReturnsEnumerableNonTupleNonNonNullTupleNonNullNon", + NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable?, int>?>? MethodReturnsEnumerableNullStructNullNonNonTupleNonNullNull() => null; + yield return new object[] { "MethodReturnsEnumerableNullStructNullNonNullTupleNonNullNull", + NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable?, int>?>? MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull() => null; + yield return new object[] { "MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull", + NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable<(GenericStruct str, int? count)> MethodReturnsEnumerableNonValueTupleNonNullNonTupleNonNullNon() => null!; + yield return new object[] { "MethodReturnsEnumerableNonValueTupleNonNullNonStructNonNullNon", + NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable }; + } + + [Theory] + [MemberData(nameof(NestedGenericsReturnParameterData))] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void NestedGenericsReturnParameterTest(string methodName, NullabilityState enumState, NullabilityState innerTupleState, + NullabilityState intState, NullabilityState outerTupleState, NullabilityState stringState, NullabilityState objectState) + { + NullabilityInfo enumerabeNullability = nullabilityContext.Create(typeof(TypeWithNotNullContext).GetMethod(methodName, flags)!.ReturnParameter); + Assert.Equal(enumState, enumerabeNullability.ReadState); + NullabilityInfo tupleNullability = enumerabeNullability.GenericTypeArguments[0]; + Assert.Equal(outerTupleState, tupleNullability.ReadState); + Assert.Equal(innerTupleState, tupleNullability.GenericTypeArguments[0].ReadState); + Assert.Equal(intState, tupleNullability.GenericTypeArguments[1].ReadState); + NullabilityInfo valueTupleNullability = tupleNullability.GenericTypeArguments[0]; + Assert.Equal(innerTupleState, valueTupleNullability.ReadState); + Assert.Equal(stringState, valueTupleNullability.GenericTypeArguments[0].ReadState); + Assert.Equal(objectState, valueTupleNullability.GenericTypeArguments[1].ReadState); + } + public static IEnumerable RefReturnData() { yield return new object[] { "RefReturnUnknown", NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown }; @@ -846,6 +954,8 @@ public void TestValueTupleGenericTypeParameters(string fieldName, NullabilitySta public class TypeWithNullableContext { #nullable disable + [AllowNull] public string PropertyDisabledAllowNull { get; set; } + [MaybeNull] public string PropertyDisabledMaybeNull { get; set; } public string PropertyDisabled { get; set; } public ref string RefReturnUnknown(ref string id) { return ref id; } #nullable enable @@ -858,12 +968,13 @@ public class TypeWithNullableContext bool NotNullWhenParameter([DisallowNull] string? disallowNull, [NotNullWhen(true)] ref string? notNullWhen, Type? nullableType) { return false; } public bool MaybeNullParameters([MaybeNull] string maybeNull, [MaybeNullWhen(false)] out string maybeNullWhen, Type? nullableType) { maybeNullWhen = null; return false; } public string? AllowNullParameter([AllowNull] string allowNull, [NotNullIfNotNull("allowNull")] string? notNullIfNotNull) { return null; } - [return: NotNullIfNotNull("nullable")] public string? NullablNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) { readNotNull = string.Empty; return null!; } + [return: NotNullIfNotNull("nullable")] public string? NullableNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) { readNotNull = string.Empty; return null!; } public ref string? RefReturnNullable([AllowNull] ref string id) { return ref id!; } [return: MaybeNull] public ref string RefReturnMaybeNull([DisallowNull] ref string? id) { return ref id; } [return: NotNull] public ref string? RefReturnNotNull([NotNull] ref string? id) { id = string.Empty; return ref id!; } public ref string RefReturnNotNullable([MaybeNull] ref string id) { return ref id; } public bool TryGetOutParameters(string id, [NotNullWhen(true)] out string? value, [MaybeNullWhen(false)] out string value2) { value = null; value2 = null; return false; } + public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; } public class TypeWithNoContext @@ -880,8 +991,6 @@ public class TypeWithNoContext public string? PropertyEnabledNullable { get; set; } public string PropertyEnabledNonNullable { get; set; } = null!; #nullable disable - [return: NotNull, MaybeNull] - public string MethodNullableDisabled([AllowNull] string value, string ret) { return null; } } public class TypeWithNotNullContext @@ -970,14 +1079,24 @@ public void MethodParametersUnknown(string s, IDictionary dict) [return: NotNull, MaybeNull] public string[]? MethodReturnsNonNotNull() => null!; // only NotNull is applicable [return: MaybeNull] public string[] MethodReturnsNonMaybeNull() => null; public string[] MethodReturnsNonNon() => null!; - public Tuple? MethodTupleNullNonNull() => null; - public IEnumerable?> MethodEnumerableNonNonNullUnknownNullNonNullNon() => null!; + public Tuple? MethodReturnsTupleNullNonNull() => null; + public Tuple MethodReturnsTupleNullNonNot() => null!; + public (int?, string)? MethodReturnsValueTupleNullNonNull() => null; + public (string?, string) MethodReturnsValueTupleNullNonNon() => (null, string.Empty); + public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; + public IEnumerable?>? MethodReturnsEnumerableNullTupleNullNonNullValueTupleNullNonNull() => null!; + public IEnumerable, int>?> MethodReturnsEnumerableNonTupleNonNonNullTupleNonNullNon() => null!; + public IEnumerable?, int>?>? MethodReturnsEnumerableNullStructNullNonNullTupleNonNullNull() => null; + public IEnumerable?, int>?>? MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull() => null; + public IEnumerable<(GenericStruct str, int? count)> MethodReturnsEnumerableNonValueTupleNonNullNonStructNonNullNon() => null!; public void MethodNullNonNullNonNon(string? s, IDictionary dict) { } public void MethodNonNullNonNullNotNull(string s, [NotNull] IDictionary? dict) { dict = new Dictionary(); } public void MethodNullNonNullNullNon(string? s, IDictionary dict) { } public void MethodAllowNullNonNonNonNull([AllowNull] string s, IDictionary? dict) { } } + public struct GenericStruct { } + internal class GenericTest { #nullable disable @@ -1041,6 +1160,7 @@ internal class GenericTestConstrainedNotNull where T : notnull public T FieldNullableEnabled = default!; public T? FieldNullable; public T PropertyNullableEnabled { get; set; } = default!; + public T? PropertyNullable { get; set; } = default!; } internal class GenericTestConstrainedStruct where T : struct @@ -1053,5 +1173,6 @@ internal class GenericTestConstrainedStruct where T : struct public T FieldNullableEnabled; public T? FieldNullable; public T PropertyNullableEnabled { get; set; } + public T? PropertyNullable { get; set; } } }