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 @@ -1177,11 +1177,26 @@ class Namer { typer: Typer =>
1177
1177
def canForward(mbr: SingleDenotation, alias: TermName): CanForward = {
1178
1178
import CanForward.*
1179
1179
val sym = mbr.symbol
1180
+ /**
1181
+ * The export selects a member of the current class (issue #22147).
1182
+ * Assumes that cls.classInfo.selfType.derivesFrom(sym.owner) is true.
1183
+ */
1184
+ def isCurrentClassMember: Boolean = expr match
1185
+ case id: (Ident | This) => // Access through self type or this
1186
+ /* Given the usage context below, where cls's self type is a subtype of sym.owner,
1187
+ it suffices to check if symbol is the same class. */
1188
+ cls == id.symbol
1189
+ case _ => false
1180
1190
if !sym.isAccessibleFrom(pathType) then
1181
1191
No("is not accessible")
1182
1192
else if sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge) || sym.is(ConstructorProxy) || sym.isAllOf(JavaModule) then
1183
1193
Skip
1184
- else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
1194
+ // if the cls is a subclass or mixes in the owner of the symbol
1195
+ // and either
1196
+ // * the symbols owner is the cls itself
1197
+ // * the symbol is not a deferred symbol
1198
+ // * the symbol is a member of the current class (#22147)
1199
+ else if cls.classInfo.selfType.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred) || isCurrentClassMember) then
1185
1200
No(i"is already a member of $cls")
1186
1201
else if pathMethod.exists && mbr.isType then
1187
1202
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