Skip to content
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

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Copy link
Member

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.

{
return ThisReference(syntax, currentType, wasCompilerGenerated: true);
}
Expand Down Expand Up @@ -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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here.

{
bool hasErrors = false;
if (EnclosingNameofArgument != node)
Expand Down
Loading