public void EnforcedInMethodBody_MaybeNullWhen_NotNullableTypes(string type)
{
{
var source = @"
var source = @"
#nullable enable
#nullable enable
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
class C<TClass>
class C<TClass, TNotNull>
where TClass : class
where TClass : class
where TNotNull : notnull
{
{
static bool TryGetValue(TClass x, [MaybeNullWhen(true)] out TClass y)
static bool TryGetValue(TYPE x, [MaybeNullWhen(true)] out TYPE y)
{
{
y = x;
y = x;
return y == null;
return y == null;
}
}
static bool TryGetValue2(TClass x, [MaybeNullWhen(true)] out TClass y)
static bool TryGetValue2(TYPE x, [MaybeNullWhen(true)] out TYPE y)
{
{
y = x;
y = x;
return y != null; // 1
return y != null; // 1
}
}
static bool TryGetValue3(TClass x, [MaybeNullWhen(false)] out TClass y)
static bool TryGetValue3(TYPE x, [MaybeNullWhen(false)] out TYPE y)
{
{
y = x;
y = x;
return y == null; // 2
return y == null; // 2
}
}
static bool TryGetValue4(TClass x, [MaybeNullWhen(false)] out TClass y)
static bool TryGetValue4(TYPE x, [MaybeNullWhen(false)] out TYPE y)
{
{
y = x;
y = x;
return y != null;
return y != null;
}
}
}
}
";
";
var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, source });
var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, source.Replace("TYPE", type) });
comp.VerifyDiagnostics(
comp.VerifyDiagnostics(
// (17,9): error CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// (18,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'false'.
// return y != null; // 1
// return y != null; // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y != null;").WithArguments("y", "false").WithLocation(17, 9),
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y != null;").WithArguments("y", "false").WithLocation(18, 9),
// (23,9): error CS8762: Parameter 'y' must have a non-null value when exiting with 'true'.
// (24,9): warning CS8762: Parameter 'y' must have a non-null value when exiting with 'true'.
// return y == null; // 2
// return y == null; // 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y == null;").WithArguments("y", "true").WithLocation(23, 9)
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return y == null;").WithArguments("y", "true").WithLocation(24, 9)
);
);
}
}
...
@@ -36133,11 +36134,8 @@ public class Derived : Base
...
@@ -36133,11 +36134,8 @@ public class Derived : Base
}
}
";
";
var comp = CreateNullableCompilation(new[] { MaybeNullWhenAttributeDefinition, source });
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
// 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
// https://github.com/dotnet/roslyn/issues/41368
// Note: assignment of `[MaybeNull] TNotNull` to `TNotNull` is currently not detected
// This is a known issue: https://github.com/dotnet/roslyn/issues/41437
comp.VerifyDiagnostics(
comp.VerifyDiagnostics(
// (14,26): warning CS8765: Type of parameter 't2' doesn't match overridden member because of nullability attributes.
// (14,26): warning CS8765: Type of parameter 't2' doesn't match overridden member because of nullability attributes.
// public override bool F2<T>([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
// public override bool F2<T>([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
...
@@ -36148,6 +36146,29 @@ public class Derived : Base
...
@@ -36148,6 +36146,29 @@ public class Derived : Base