File tree Expand file tree Collapse file tree 4 files changed +72
-2
lines changed
compiler/src/dotty/tools/dotc/typer Expand file tree Collapse file tree 4 files changed +72
-2
lines changed Original file line number Diff line number Diff line change @@ -1175,11 +1175,26 @@ class Namer { typer: Typer =>
11751175 def canForward (mbr : SingleDenotation , alias : TermName ): CanForward = {
11761176 import CanForward .*
11771177 val sym = mbr.symbol
1178+ /**
1179+ * The export selects a member of the current class (issue #22147).
1180+ * Assumes that cls.classInfo.selfType.derivesFrom(sym.owner) is true.
1181+ */
1182+ def isCurrentClassMember : Boolean = expr match
1183+ case id : (Ident | This ) => // Access through self type or this
1184+ /* Given the usage context below, where cls's self type is a subtype of sym.owner,
1185+ it suffices to check if symbol is the same class. */
1186+ cls == id.symbol
1187+ case _ => false
11781188 if ! sym.isAccessibleFrom(pathType) then
11791189 No (" is not accessible" )
11801190 else if sym.isConstructor || sym.is(ModuleClass ) || sym.is(Bridge ) || sym.is(ConstructorProxy ) || sym.isAllOf(JavaModule ) then
11811191 Skip
1182- else if cls.derivesFrom(sym.owner) && (sym.owner == cls || ! sym.is(Deferred )) then
1192+ // if the cls is a subclass or mixes in the owner of the symbol
1193+ // and either
1194+ // * the symbols owner is the cls itself
1195+ // * the symbol is not a deferred symbol
1196+ // * the symbol is a member of the current class (#22147)
1197+ else if cls.classInfo.selfType.derivesFrom(sym.owner) && (sym.owner == cls || ! sym.is(Deferred ) || isCurrentClassMember) then
11831198 No (i " is already a member of $cls" )
11841199 else if pathMethod.exists && mbr.isType then
11851200 No (" is a type, so it cannot be exported as extension method" )
Original file line number Diff line number Diff line change 1+ trait P :
2+ def foo : Int
3+
4+ class A extends P :
5+ export this .foo // error
6+
7+ trait Q extends P :
8+ def bar : Int
9+
10+ trait R extends P :
11+ def baz : Int
12+ val a1 : A
13+ val a2 : A
14+
15+ abstract class B extends R :
16+ self =>
17+ export this .baz // error
18+ export self .bar // error
19+ export this .a1 .foo
20+ export self .a2 .foo // error
21+ export a2 .foo // error
22+
23+ abstract class D extends P :
24+ val p : P
25+ export p .foo
26+
27+ abstract class E :
28+ self : P =>
29+ export self .foo // error
30+
31+ abstract class F :
32+ self : P =>
33+ export this .foo // error
34+
35+ class G (p : P ):
36+ self : P =>
37+ export p .foo
38+
39+ class H (p : P ):
40+ self : P =>
41+ export this .p .foo
Original file line number Diff line number Diff line change 1515 | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace.
1616 |
1717 | longer explanation available when compiling with `-explain`
18+ -- [E046] Cyclic Error: tests/neg/i20245/Typer_2.scala:10:7 ------------------------------------------------------------
19+ 10 |import effekt.source.{ resolve } // error
20+ | ^
21+ | Cyclic reference involving class Context
22+ |
23+ | The error occurred while trying to compute the base classes of class Context
24+ | which required to compute the base classes of trait TyperOps
25+ | which required to compute the signature of trait TyperOps
26+ | which required to elaborate the export clause export unification.requireSubtype
27+ | which required to compute the base classes of class Context
28+ |
29+ | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace.
30+ |
31+ | longer explanation available when compiling with `-explain`
Original file line number Diff line number Diff line change @@ -7,7 +7,7 @@ import effekt.util.messages.ErrorReporter
77import effekt .context .{ Context }
88
99// This import is also NECESSARY for the cyclic error
10- import effekt .source .{ resolve }
10+ import effekt .source .{ resolve } // error
1111
1212
1313trait TyperOps extends ErrorReporter { self : Context =>
You can’t perform that action at this time.
0 commit comments