From 61b8eed0830a9376e18eabee21e193ed919c935c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 6 Jun 2020 18:46:10 +0200 Subject: [PATCH 1/2] Avoid time travel when handling of LazyRefs The idea of LazyRefs is that they are always completed in the current context. But that did not work if the LazyRef is mapped in a type map. Here, the TypeMap's context was used to do the remap. We now use the context that forced the LazyVal instead. The problem manifested itself with failing replTests when the new implicitScope scheme was used. --- .../src/dotty/tools/dotc/core/TypeApplications.scala | 2 +- compiler/src/dotty/tools/dotc/core/Types.scala | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index f66e9f35fae2..12ea35ba1c62 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -337,7 +337,7 @@ class TypeApplications(val self: Type) extends AnyVal { case dealiased: TypeBounds => dealiased.derivedTypeBounds(dealiased.lo.appliedTo(args), dealiased.hi.appliedTo(args)) case dealiased: LazyRef => - LazyRef(c => dealiased.ref(c).appliedTo(args)) + LazyRef(c => dealiased.ref(c).appliedTo(args)(using c)) case dealiased: WildcardType => WildcardType(dealiased.optBounds.orElse(TypeBounds.empty).appliedTo(args).bounds) case dealiased: TypeRef if dealiased.symbol == defn.NothingClass => diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 9aa181bd2b02..6ab8c7034c45 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4862,7 +4862,7 @@ object Types { } } - abstract class TypeMap(implicit protected val mapCtx: Context) + abstract class TypeMap(implicit protected var mapCtx: Context) extends VariantTraversal with (Type => Type) { thisMap => protected def stopAtStatic: Boolean = true @@ -4979,7 +4979,12 @@ object Types { derivedSuperType(tp, this(thistp), this(supertp)) case tp: LazyRef => - LazyRef(_ => this(tp.ref)) + LazyRef { c => + val saved = mapCtx + mapCtx = c + try this(tp.ref(using c)) + finally mapCtx = saved + } case tp: ClassInfo => mapClassInfo(tp) From 72429b21a3550811acb5988e999971fcbc56cb14 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 6 Jun 2020 20:04:47 +0200 Subject: [PATCH 2/2] Only update runId when forcing a LazyRef in a map --- compiler/src/dotty/tools/dotc/core/Types.scala | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 6ab8c7034c45..e94ea2388ab2 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4980,10 +4980,14 @@ object Types { case tp: LazyRef => LazyRef { c => - val saved = mapCtx - mapCtx = c - try this(tp.ref(using c)) - finally mapCtx = saved + val ref1 = tp.ref(using c) + if c.runId == mapCtx.runId then this(ref1) + else // splice in new run into map context + val saved = mapCtx + mapCtx = mapCtx.fresh + .setPeriod(Period(c.runId, mapCtx.phaseId)) + .setRun(c.run) + try this(ref1) finally mapCtx = saved } case tp: ClassInfo =>