未验证 提交 69662045 编写于 作者: V Vladimir Sadov 提交者: GitHub

Merge pull request #33984 from VSadov/nullableBoxing

Check nullness of a nullable receiver when invoking base methods.
...@@ -2522,9 +2522,24 @@ private TypeWithState VisitCallReceiver(BoundCall node) ...@@ -2522,9 +2522,24 @@ private TypeWithState VisitCallReceiver(BoundCall node)
if (receiverOpt != null && node.Method.MethodKind != MethodKind.Constructor) if (receiverOpt != null && node.Method.MethodKind != MethodKind.Constructor)
{ {
receiverType = VisitRvalueWithState(receiverOpt); receiverType = VisitRvalueWithState(receiverOpt);
// methods which are members of Nullable<T> (ex: ToString, GetHashCode) can be invoked on null receiver.
// However, inherited methods (ex: GetType) are invoked on a boxed value (since base types are reference types)
// and therefore in those cases nullable receivers should be checked for nullness.
bool checkNullableValueType = false;
var type = receiverType.Type;
var method = node.Method;
if (!method.IsStatic &&
type?.IsNullableType() == true &&
method.ContainingType.IsReferenceType)
{
checkNullableValueType = true;
}
// https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null // https://github.com/dotnet/roslyn/issues/30598: Mark receiver as not null
// after arguments have been visited, and only if the receiver has not changed. // after arguments have been visited, and only if the receiver has not changed.
CheckPossibleNullReceiver(receiverOpt); CheckPossibleNullReceiver(receiverOpt, checkNullableValueType);
} }
return receiverType; return receiverType;
......
...@@ -78913,6 +78913,50 @@ static void F6(T? t6) ...@@ -78913,6 +78913,50 @@ static void F6(T? t6)
); );
} }
[WorkItem(33174, "https://github.com/dotnet/roslyn/issues/33174")]
[Fact]
public void NullableBaseMembers()
{
var source =
@"
static class Program
{
static void Main()
{
int? x = null;
x.GetHashCode(); // ok
x.Extension(); // ok
x.GetType(); // warning1
int? y = null;
y.MemberwiseClone(); // warning2
y.Lalala(); // does not exist
}
static void Extension(this int? self) { }
}
";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics(
// (12,9): warning CS8629: Nullable value type may be null.
// x.GetType(); // warning1
Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(12, 9),
// (15,9): warning CS8629: Nullable value type may be null.
// y.MemberwiseClone(); // warning2
Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "y").WithLocation(15, 9),
// (15,11): error CS1540: Cannot access protected member 'object.MemberwiseClone()' via a qualifier of type 'int?'; the qualifier must be of type 'Program' (or derived from it)
// y.MemberwiseClone(); // warning2
Diagnostic(ErrorCode.ERR_BadProtectedAccess, "MemberwiseClone").WithArguments("object.MemberwiseClone()", "int?", "Program").WithLocation(15, 11),
// (17,11): error CS1061: 'int?' does not contain a definition for 'Lalala' and no accessible extension method 'Lalala' accepting a first argument of type 'int?' could be found (are you missing a using directive or an assembly reference?)
// y.Lalala(); // does not exist
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Lalala").WithArguments("int?", "Lalala").WithLocation(17, 11)
);
}
[Fact] [Fact]
public void NullableT_Using() public void NullableT_Using()
{ {
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册