-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable implicit “this” in default interface implementations. #18393
Enable implicit “this” in default interface implementations. #18393
Conversation
I2.set_P3 | ||
I2.add_E3 | ||
I2.remove_E3 | ||
I2.get_P2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider some additional formatting to improve readability. Maybe add "## " on the "headers".
|
||
CompileAndVerify(compilation1, verify: false); | ||
|
||
/* Expected output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PROTOTYPE?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running success scenarios is tracked in #17952.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@dotnet/roslyn-compiler Please review, need a second sign-off. |
@@ -1319,7 +1319,7 @@ private BoundExpression SynthesizeMethodGroupReceiver(CSharpSyntaxNode syntax, A | |||
var declaringType = members[0].ContainingType; | |||
|
|||
HashSet<DiagnosticInfo> unused = null; | |||
if (currentType.IsEqualToOrDerivedFrom(declaringType, TypeCompareKind.ConsiderEverything, useSiteDiagnostics: ref unused)) | |||
if (currentType.IsInterface || currentType.IsEqualToOrDerivedFrom(declaringType, TypeCompareKind.ConsiderEverything, useSiteDiagnostics: ref unused)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct for an interface nested within a class that does not implement the interface. If we find a method invocation of an instance method of the enclosing class, this would appear to return an incompatible "this". The design of this method would appear to require that null
be returned rather than an incompatible receiver. Here is the scenario:
class A
{
public void M() {}
interface I
{
void N() { M(); } // what `this` here?
}
}
I suspect the correct fix is to use something other than (or modify) IsEqualToOrDerivedFrom
, which considers only non-interface inheritance.
The alternative is to remove the test for reference-relatedness from this method entirely and rely on a mechanism for that to be checked elsewhere, if you believe that such a larger refactoring has other benefits.
Please add tests for nested types, and specifically implicit receivers for invocations of names found on or inherited into enclosing types.
@@ -1538,7 +1538,7 @@ private BoundExpression SynthesizeReceiver(CSharpSyntaxNode node, Symbol member, | |||
var currentType = this.ContainingType; | |||
HashSet<DiagnosticInfo> useSiteDiagnostics = null; | |||
|
|||
if (currentType.IsEqualToOrDerivedFrom(member.ContainingType, TypeCompareKind.ConsiderEverything, useSiteDiagnostics: ref useSiteDiagnostics)) | |||
if (currentType.IsInterface || currentType.IsEqualToOrDerivedFrom(member.ContainingType, TypeCompareKind.ConsiderEverything, useSiteDiagnostics: ref useSiteDiagnostics)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue here.
@gafter I believe I've addressed your feedback, please take a look. |
@dotnet/roslyn-compiler Please review, need a second sign-off. |
@@ -1319,7 +1319,8 @@ private BoundExpression SynthesizeMethodGroupReceiver(CSharpSyntaxNode syntax, A | |||
var declaringType = members[0].ContainingType; | |||
|
|||
HashSet<DiagnosticInfo> unused = null; | |||
if (currentType.IsEqualToOrDerivedFrom(declaringType, TypeCompareKind.ConsiderEverything, useSiteDiagnostics: ref unused)) | |||
if (currentType.IsEqualToOrDerivedFrom(declaringType, TypeCompareKind.ConsiderEverything, useSiteDiagnostics: ref unused) || | |||
(currentType.IsInterface && (declaringType.IsObjectType() || currentType.AllInterfacesNoUseSiteDiagnostics.Contains(declaringType)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
( [](start = 16, length = 1)
This is not correct for an invocation of an interface method from a class nested within the interface. Although you have not implemented classes declared within interfaces yet, I do not think it makes sense to add code here that will just have to be changed again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there tests that distinguish this if
statement's condition from (currentType == declaringType)
thereby illustrating the importance of the test for related types here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see declaringType
has nothing to do with the T
quoted in the spec, above. That means that the "If T is the instance type of the immediately enclosing class or struct type..." part of the quoted spec isn't implemented. Anywhere. This relatedness test appears intended to imitate that test, but it does not do so correctly in cases involving hiding. As a consequence, this implementation would appear to get the hiding cases wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I filed a bug for the existing issue about hiding in nested scenarios.
@dotnet/roslyn-compiler Please review.