Skip to content

Commit b3a1bd0

Browse files
liufengyuntanishiking
authored andcommitted
Handle OuterSelect in init checker
1 parent be97cad commit b3a1bd0

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Contexts._
77
import Symbols._
88
import Types._
99
import StdNames._
10+
import NameKinds.OuterSelectName
1011

1112
import ast.tpd._
1213
import util.EqHashMap
@@ -797,7 +798,15 @@ class Semantic {
797798
res.call(id.symbol, args, superType = NoType, source = expr)
798799

799800
case Select(qualifier, name) =>
800-
eval(qualifier, thisV, klass).select(expr.symbol, expr)
801+
val qualRes = eval(qualifier, thisV, klass)
802+
803+
name match
804+
case OuterSelectName(_, hops) =>
805+
val SkolemType(tp) = expr.tpe
806+
val outer = resolveOuterSelect(tp.classSymbol.asClass, qualRes.value, hops, source = expr)
807+
Result(outer, qualRes.errors)
808+
case _ =>
809+
qualRes.select(expr.symbol, expr)
801810

802811
case _: This =>
803812
cases(expr.tpe, thisV, klass, expr)
@@ -963,6 +972,40 @@ class Semantic {
963972

964973
}
965974

975+
/** Resolve outer select introduced during inlining.
976+
*
977+
* See `tpd.outerSelect` and `ElimOuterSelect`.
978+
*/
979+
def resolveOuterSelect(target: ClassSymbol, thisV: Value, hops: Int, source: Tree): Contextual[Value] = log("resolving outer " + target.show + ", this = " + thisV.show + ", hops = " + hops, printer, res => res.asInstanceOf[Value].show) {
980+
// Is `target` reachable from `cls` with the given `hops`?
981+
def reachable(cls: ClassSymbol, hops: Int): Boolean =
982+
if hops == 0 then cls == target
983+
else reachable(cls.lexicallyEnclosingClass.asClass, hops - 1)
984+
985+
thisV match
986+
case Hot => Hot
987+
988+
case addr: Addr =>
989+
val obj = heap(addr)
990+
val curOpt = obj.klass.baseClasses.find(cls => reachable(cls, hops))
991+
curOpt match
992+
case Some(cur) =>
993+
resolveThis(target, thisV, cur, source)
994+
995+
case None =>
996+
report.warning("unexpected outerSelect, thisV = " + thisV + ", target = " + target.show + ", hops = " + hops, source.srcPos)
997+
Cold
998+
999+
case RefSet(refs) =>
1000+
refs.map(ref => resolveOuterSelect(target, ref, hops, source)).join
1001+
1002+
case fun: Fun =>
1003+
report.warning("unexpected thisV = " + thisV + ", target = " + target.show + ", hops = " + hops, source.srcPos)
1004+
Cold
1005+
1006+
case Cold => Cold
1007+
}
1008+
9661009
/** Compute the outer value that correspond to `tref.prefix` */
9671010
def outerValue(tref: TypeRef, thisV: Addr, klass: ClassSymbol, source: Tree): Contextual[Result] =
9681011
val cls = tref.classSymbol.asClass

tests/init/crash/i8892.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
trait Reporter:
2+
def report(m: String): Unit
3+
4+
class Dummy extends Reporter:
5+
def report(m: String) = ()
6+
7+
object ABug {
8+
sealed trait Nat {
9+
transparent inline def ++ : Succ[this.type] = Succ(this)
10+
11+
transparent inline def +(inline that: Nat): Nat =
12+
inline this match {
13+
case Zero => that
14+
case Succ(p) => p + that.++
15+
}
16+
}
17+
18+
case object Zero extends Nat
19+
case class Succ[N <: Nat](p: N) extends Nat
20+
21+
transparent inline def toIntg(inline n: Nat): Int =
22+
inline n match {
23+
case Zero => 0
24+
case Succ(p) => toIntg(p) + 1
25+
}
26+
27+
val j31 = toIntg(Zero.++.++.++ + Zero.++)
28+
}

0 commit comments

Comments
 (0)