Skip to content

Commit

Permalink
Merge pull request #15606 from dotty-staging/fix-15465
Browse files Browse the repository at this point in the history
Fix #15465: Use resolveThis for outerSelect resolution
  • Loading branch information
liufengyun authored Jul 7, 2022
2 parents 22080c5 + b274576 commit ae83f76
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 41 deletions.
49 changes: 8 additions & 41 deletions compiler/src/dotty/tools/dotc/transform/init/Semantic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -779,8 +779,8 @@ object Semantic:
if tryReporter.errors.nonEmpty && isSyntheticApply(meth) then
tryReporter.abort()
val klass = meth.owner.companionClass.asClass
val outerCls = klass.owner.lexicallyEnclosingClass.asClass
val outer = resolveOuterSelect(outerCls, ref, 1)
val targetCls = klass.owner.lexicallyEnclosingClass.asClass
val outer = resolveThis(targetCls, ref, meth.owner.asClass)
outer.instantiate(klass, klass.primaryConstructor, args)
else
reporter.reportAll(tryReporter.errors)
Expand Down Expand Up @@ -1322,9 +1322,12 @@ object Semantic:
val qual = eval(qualifier, thisV, klass)

name match
case OuterSelectName(_, hops) =>
val SkolemType(tp) = expr.tpe: @unchecked
withTrace(trace2) { resolveOuterSelect(tp.classSymbol.asClass, qual, hops) }
case OuterSelectName(_, _) =>
val current = qualifier.tpe.classSymbol
val target = expr.tpe.widenSingleton.classSymbol.asClass
withTrace(trace2) {
resolveThis(target, qual, current.asClass)
}
case _ =>
withTrace(trace2) { qual.select(expr.symbol) }

Expand Down Expand Up @@ -1493,42 +1496,6 @@ object Semantic:

}

/** Resolve outer select introduced during inlining.
*
* See `tpd.outerSelect` and `ElimOuterSelect`.
*/
def resolveOuterSelect(target: ClassSymbol, thisV: Value, hops: Int): Contextual[Value] = log("resolving outer " + target.show + ", this = " + thisV.show + ", hops = " + hops, printer, (_: Value).show) {
// Is `target` reachable from `cls` with the given `hops`?
def reachable(cls: ClassSymbol, hops: Int): Boolean = log("reachable from " + cls + " -> " + target + " in " + hops, printer) {
if hops == 0 then cls == target
else reachable(cls.owner.lexicallyEnclosingClass.asClass, hops - 1)
}

thisV match
case Hot => Hot

case ref: Ref =>
val obj = ref.objekt
val curOpt = obj.klass.baseClasses.find(cls => reachable(cls, hops))
curOpt match
case Some(cur) =>
resolveThis(target, thisV, cur)

case None =>
// TODO: use error once we fix https://github.com/lampepfl/dotty/issues/15465
report.warning("[Internal error] unexpected outerSelect, thisV = " + thisV + ", target = " + target.show + ", hops = " + hops, trace.toVector.last.srcPos)
Cold

case RefSet(refs) =>
refs.map(ref => resolveOuterSelect(target, ref, hops)).join

case fun: Fun =>
report.error("[Internal error] unexpected thisV = " + thisV + ", target = " + target.show + ", hops = " + hops, trace.toVector.last.srcPos)
Cold

case Cold => Cold
}

/** Compute the outer value that correspond to `tref.prefix` */
def outerValue(tref: TypeRef, thisV: Ref, klass: ClassSymbol): Contextual[Value] =
val cls = tref.classSymbol.asClass
Expand Down
17 changes: 17 additions & 0 deletions tests/init/pos/i15465.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class TestSuite:
protected val it = new ItWord

protected final class ItWord:
def should(string: String) = new ItVerbString("should", string)

private def registerTestToRun(fun: => Any): Unit = ()

protected final class ItVerbString(verb: String, name: String):
inline def in(testFun: => Any): Unit = registerTestToRun(testFun)

class MyTest extends TestSuite:
it should "not cause outer select errors" in {
assert(1 + 1 == 2)
}

val n = 10

0 comments on commit ae83f76

Please sign in to comment.