未验证 提交 6db969b4 编写于 作者: R Rikki Gibson 提交者: GitHub

Fix crash for Equals analysis of types with bad base clauses (#42968)

上级 f2742863
......@@ -3958,12 +3958,14 @@ private void ReinferMethodAndVisitArguments(BoundCall node, TypeWithState receiv
SetUpdatedSymbol(node, node.Method, method);
}
#nullable enable
private void LearnFromEqualsMethod(MethodSymbol method, BoundCall node, TypeWithState receiverType, ImmutableArray<VisitArgumentResult> results)
{
// easy out
var parameterCount = method.ParameterCount;
var arguments = node.Arguments;
if ((parameterCount != 1 && parameterCount != 2)
if (node.HasErrors
|| (parameterCount != 1 && parameterCount != 2)
|| parameterCount != arguments.Length
|| method.MethodKind != MethodKind.Ordinary
|| method.ReturnType.SpecialType != SpecialType.System_Boolean
......@@ -3986,11 +3988,12 @@ private void LearnFromEqualsMethod(MethodSymbol method, BoundCall node, TypeWith
var isObjectEqualsMethodOrOverride = method.GetLeastOverriddenMethod(accessingTypeOpt: null)
.Equals(compilation.GetSpecialTypeMember(SpecialMember.System_Object__Equals));
if (isObjectEqualsMethodOrOverride ||
isWellKnownEqualityMethodOrImplementation(compilation, method, receiverType.Type, WellKnownMember.System_IEquatable_T__Equals))
if (node.ReceiverOpt is BoundExpression receiver &&
(isObjectEqualsMethodOrOverride ||
isWellKnownEqualityMethodOrImplementation(compilation, method, receiverType.Type, WellKnownMember.System_IEquatable_T__Equals)))
{
Debug.Assert(arguments.Length == 1);
learnFromEqualsMethodArguments(node.ReceiverOpt, receiverType, arguments[0], results[0].RValueType);
learnFromEqualsMethodArguments(receiver, receiverType, arguments[0], results[0].RValueType);
return;
}
......@@ -4007,9 +4010,9 @@ static bool anyOverriddenMethodHasExplicitImplementation(MethodSymbol method)
return false;
}
static bool isWellKnownEqualityMethodOrImplementation(CSharpCompilation compilation, MethodSymbol method, TypeSymbol receiverType, WellKnownMember wellKnownMember)
static bool isWellKnownEqualityMethodOrImplementation(CSharpCompilation compilation, MethodSymbol method, TypeSymbol? receiverType, WellKnownMember wellKnownMember)
{
var wellKnownMethod = (MethodSymbol)compilation.GetWellKnownTypeMember(wellKnownMember);
var wellKnownMethod = (MethodSymbol?)compilation.GetWellKnownTypeMember(wellKnownMember);
if (wellKnownMethod is null || receiverType is null)
{
return false;
......@@ -4120,6 +4123,7 @@ void learnFromEqualsMethodArguments(BoundExpression left, TypeWithState leftType
}
}
}
#nullable restore
private bool IsCompareExchangeMethod(MethodSymbol method)
{
......
......@@ -123946,6 +123946,58 @@ static void M1(C c, string? s)
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(18, 15));
}
[Fact, WorkItem(42960, "https://github.com/dotnet/roslyn/issues/42960")]
public void EqualsMethod_IncompleteBaseClause()
{
var source = @"
class C :
{
void M(C? other)
{
if (Equals(other)) { other.ToString(); }
if (this.Equals(other)) { other.ToString(); }
}
}
";
var comp = CreateNullableCompilation(source);
comp.VerifyDiagnostics(
// (2,10): error CS1031: Type expected
// class C :
Diagnostic(ErrorCode.ERR_TypeExpected, "").WithLocation(2, 10),
// (6,13): error CS0120: An object reference is required for the non-static field, method, or property 'object.Equals(object)'
// if (Equals(other)) { other.ToString(); }
Diagnostic(ErrorCode.ERR_ObjectRequired, "Equals").WithArguments("object.Equals(object)").WithLocation(6, 13),
// (6,30): warning CS8602: Dereference of a possibly null reference.
// if (Equals(other)) { other.ToString(); }
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "other").WithLocation(6, 30));
}
[Fact, WorkItem(42960, "https://github.com/dotnet/roslyn/issues/42960")]
public void EqualsMethod_ErrorBaseClause()
{
var source = @"
class C : ERROR
{
void M(C? other)
{
if (Equals(other)) { other.ToString(); }
if (this.Equals(other)) { other.ToString(); }
}
}
";
var comp = CreateNullableCompilation(source);
comp.VerifyDiagnostics(
// (2,11): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?)
// class C : ERROR
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(2, 11),
// (6,13): error CS0120: An object reference is required for the non-static field, method, or property 'object.Equals(object)'
// if (Equals(other)) { other.ToString(); }
Diagnostic(ErrorCode.ERR_ObjectRequired, "Equals").WithArguments("object.Equals(object)").WithLocation(6, 13),
// (6,30): warning CS8602: Dereference of a possibly null reference.
// if (Equals(other)) { other.ToString(); }
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "other").WithLocation(6, 30));
}
[Fact]
[WorkItem(36131, "https://github.com/dotnet/roslyn/issues/36131")]
public void ShouldRunNullableWalker_GlobalDirective()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册