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

Exports: Refine canForward for selections on this #22503

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 16 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1175,11 +1175,26 @@ class Namer { typer: Typer =>
def canForward(mbr: SingleDenotation, alias: TermName): CanForward = {
import CanForward.*
val sym = mbr.symbol
/**
* Check the export selects an abstract member of the current class (issue #22147).
*/
def isAbstractMember: Boolean = sym.is(Deferred) && (expr match
case ths: This if ths.qual.isEmpty => true // access through 'this'
case id: Ident => id.denot.info match // access through self type
case cls2: ClassInfo => cls2.cls == cls
case _ => false
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
Skip
else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
// if the cls is a subclass of the owner of the symbol
// and either
// * the symbols owner is the cls itself
// * the symbol is not a deferred symbol
// * 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
21 changes: 21 additions & 0 deletions tests/neg/exports3.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
trait P:
def foo: Int

class A extends P:
export this.foo // error

trait Q extends P:
def bar: Int

trait R extends P:
def baz: Int
val a1: A
val a2: A

class B extends R:
self =>
export this.baz // error
export self.bar // error
export this.a1.foo
export self.a2.foo // error
export a2.foo // error
Loading