File tree 4 files changed +72
-2
lines changed
compiler/src/dotty/tools/dotc/typer
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 =>
1175
1175
def canForward (mbr : SingleDenotation , alias : TermName ): CanForward = {
1176
1176
import CanForward .*
1177
1177
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
1178
1188
if ! sym.isAccessibleFrom(pathType) then
1179
1189
No (" is not accessible" )
1180
1190
else if sym.isConstructor || sym.is(ModuleClass ) || sym.is(Bridge ) || sym.is(ConstructorProxy ) || sym.isAllOf(JavaModule ) then
1181
1191
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
1183
1198
No (i " is already a member of $cls" )
1184
1199
else if pathMethod.exists && mbr.isType then
1185
1200
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 15
15
| Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace.
16
16
|
17
17
| 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
7
7
import effekt .context .{ Context }
8
8
9
9
// This import is also NECESSARY for the cyclic error
10
- import effekt .source .{ resolve }
10
+ import effekt .source .{ resolve } // error
11
11
12
12
13
13
trait TyperOps extends ErrorReporter { self : Context =>
You can’t perform that action at this time.
0 commit comments