Skip to content

Exports: Refine canForward for selections on this #22503

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

Closed
wants to merge 4 commits into from
Closed
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
Prev Previous commit
Next Next commit
Exports: Improve detection of selections on this
Fixes the typeclass-aggregates test. We now reject selections on `this`
in `canForward` only if the selection has an empty qualifier.
  • Loading branch information
bracevac committed Feb 3, 2025
commit 29c9945316c72537c849167da5f3546f9b0fd43a
11 changes: 9 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,13 @@ class Namer { typer: Typer =>
def canForward(mbr: SingleDenotation, alias: TermName): CanForward = {
import CanForward.*
val sym = mbr.symbol
/**
* Check the export selects an abstract member (issue #22147).
*/
def isAbstractMember: Boolean = sym.is(Deferred) && (expr match
case ths: This if ths.qual.isEmpty => true
case _ => false
)
if !sym.isAccessibleFrom(pathType) then
No("is not accessible")
else if sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge) || sym.is(ConstructorProxy) || sym.isAllOf(JavaModule) then
Expand All @@ -1183,8 +1190,8 @@ class Namer { typer: Typer =>
// and either
// * the symbols owner is the cls itself
// * the symbol is not a deferred symbol
// * the symbol is a deferred symbol and the selection is on a This
else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred) || (sym.is(Deferred) && expr.isInstanceOf[This])) then
// * the symbol is an abstract member #22147
else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred) || isAbstractMember) then
No(i"is already a member of $cls")
else if pathMethod.exists && mbr.isType then
No("is a type, so it cannot be exported as extension method")
Expand Down