diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 21ef0fc5d123..87bf0883aca4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -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") diff --git a/tests/neg/exports3.scala b/tests/neg/exports3.scala new file mode 100644 index 000000000000..5b15588fb0a0 --- /dev/null +++ b/tests/neg/exports3.scala @@ -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 \ No newline at end of file