Skip to content

Commit 990c933

Browse files
liufengyunsmarter
andcommitted
Fix #10769: change synthesized type in def ordinal
As pointed out by @smarter in #10769, for the following code: package stm trait STMLike[F[_]] { import Internals._ sealed abstract class Txn[+A] {} object Txn { def abort[A](e: Throwable): Txn[A] = Abort(e) } object Internals { case class Abort(error: Throwable) extends Txn[Nothing] } } The compiler synthesized the following code for the object `Txn`: object Txn { type MirroredMonoType = STMLike.this.Txn[?] def ordinal(x: Txn.MirroredMonoType): Int = x match { case _:stm.STMLike.Internals.Abort => 0 } def abort[A](e: Throwable): Txn[A] = Abort(e) } In the method `ordinal`, the type for `Internals.Abort` is TypeRef(ThisType(TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class stm)),trait STMLike)),module class Internals$)),class Abort) This type is incorrect, as we are not in the object `Internals`. The explicit outer can only handle such types if it's static. In this case, the object is not static, thus it crashes the explicit outer. Co-authored-by: Guillaume Martres <[email protected]>
1 parent 87102a0 commit 990c933

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,33 @@ object SymDenotations {
14101410
def namedType(using Context): NamedType =
14111411
if (isType) typeRef else termRef
14121412

1413+
/** The typeRef where `pre.O$.this` is changed to `pre.O.type` if `O` is a non-static object
1414+
*
1415+
* This is required to avoid owner crash in ExplicitOuter.
1416+
* See tests/pos/i10769.scala
1417+
*/
1418+
def reachableTypeRef(using Context) =
1419+
TypeRef(owner.reachableThisType, symbol)
1420+
1421+
/** The termRef where `pre.O$.this` is changed to `pre.O.type` if `O` is a non-static object
1422+
*
1423+
* This is required to avoid owner crash in ExplicitOuter.
1424+
* See tests/pos/i10769.scala
1425+
*/
1426+
def reachableTermRef(using Context) =
1427+
TermRef(owner.reachableThisType, symbol)
1428+
1429+
/** The thisType where `pre.O$.this` is changed to `pre.O.type` if `O` is a non-static object */
1430+
def reachableThisType(using Context): Type =
1431+
if this.is(Package) then
1432+
ThisType.raw(TypeRef(NoPrefix, symbol.asType))
1433+
else if this.isTerm then
1434+
NoPrefix
1435+
else if !this.isStaticOwner && this.is(Module) then
1436+
TermRef(owner.reachableThisType, this.sourceModule)
1437+
else
1438+
ThisType.raw(TypeRef(owner.reachableThisType, symbol.asType))
1439+
14131440
/** The variance of this type parameter or type member as a subset of
14141441
* {Covariant, Contravariant}
14151442
*/

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,9 @@ object SymUtils:
223223
else owner.isLocal
224224
}
225225

226-
/** The typeRef with wildcard arguments for each type parameter */
227-
def rawTypeRef(using Context) =
228-
self.typeRef.appliedTo(self.typeParams.map(_ => TypeBounds.emptyPolyKind))
226+
/** The reachable typeRef with wildcard arguments for each type parameter */
227+
def reachableRawTypeRef(using Context) =
228+
self.reachableTypeRef.appliedTo(self.typeParams.map(_ => TypeBounds.emptyPolyKind))
229229

230230
/** Is symbol a quote operation? */
231231
def isQuote(using Context): Boolean =

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
521521
else {
522522
val cases =
523523
for ((child, idx) <- cls.children.zipWithIndex) yield {
524-
val patType = if (child.isTerm) child.termRef else child.rawTypeRef
524+
val patType = if (child.isTerm) child.reachableTermRef else child.reachableRawTypeRef
525525
val pat = Typed(untpd.Ident(nme.WILDCARD).withType(patType), TypeTree(patType))
526526
CaseDef(pat, EmptyTree, Literal(Constant(idx)))
527527
}
@@ -563,7 +563,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
563563
if (existing.exists && !existing.is(Deferred)) existing
564564
else {
565565
val monoType =
566-
newSymbol(clazz, tpnme.MirroredMonoType, Synthetic, TypeAlias(linked.rawTypeRef), coord = clazz.coord)
566+
newSymbol(clazz, tpnme.MirroredMonoType, Synthetic, TypeAlias(linked.reachableRawTypeRef), coord = clazz.coord)
567567
newBody = newBody :+ TypeDef(monoType).withSpan(ctx.owner.span.focus)
568568
monoType.entered
569569
}

tests/pos/i10769.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package stm
2+
3+
trait STMLike[F[_]] {
4+
import Internals._
5+
6+
sealed abstract class Txn[+A] {}
7+
8+
object Txn {
9+
def abort[A](e: Throwable): Txn[A] = Abort(e)
10+
}
11+
12+
object Internals {
13+
case class Abort(error: Throwable) extends Txn[Nothing]
14+
case object Noop extends Txn[Nothing]
15+
}
16+
17+
class Foo {
18+
case class Abort(error: Throwable) extends Txn[Nothing]
19+
case object Noop extends Txn[Nothing]
20+
}
21+
}

0 commit comments

Comments
 (0)