diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index fb2300ff1829..9397eeb09d7b 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -443,7 +443,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(() => dealiased.ref.appliedTo(args)) + LazyRef(c => dealiased.ref(c).appliedTo(args)) case dealiased: WildcardType => WildcardType(dealiased.optBounds.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 40fbc80f85f0..0a553f72c1bb 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2149,25 +2149,23 @@ object Types { } } - case class LazyRef(private var refFn: () => Type) extends UncachedProxyType with ValueType { + case class LazyRef(private var refFn: Context => Type) extends UncachedProxyType with ValueType { private var myRef: Type = null private var computed = false - def ref = { + def ref(implicit ctx: Context) = { if (computed) assert(myRef != null) else { computed = true - myRef = refFn() + myRef = refFn(ctx) + refFn = null } myRef } def evaluating = computed && myRef == null override def underlying(implicit ctx: Context) = ref - override def toString = s"LazyRef($ref)" - override def equals(other: Any) = other match { - case other: LazyRef => this.ref.equals(other.ref) - case _ => false - } - override def hashCode = ref.hashCode + 37 + override def toString = s"LazyRef(...)" + override def equals(other: Any) = this eq other.asInstanceOf[AnyRef] + override def hashCode = System.identityHashCode(this) } // --- Refined Type and RecType ------------------------------------------------ @@ -3768,7 +3766,7 @@ object Types { derivedSuperType(tp, this(thistp), this(supertp)) case tp: LazyRef => - LazyRef(() => this(tp.ref)) + LazyRef(_ => this(tp.ref)) case tp: ClassInfo => mapClassInfo(tp) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index cd0d427f3510..3b04d6d67eb7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -164,6 +164,7 @@ Standard-Section: "ASTs" TopLevelStat* BIND Length boundName_NameRef bounds_Type // for type-variables defined in a type pattern BYNAMEtype underlying_Type + LAZYref underlying_Type POLYtype Length result_Type NamesTypes METHODtype Length result_Type NamesTypes // needed for refinements TYPELAMBDAtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing) @@ -256,7 +257,7 @@ object TastyFormat { final val OBJECTCLASS = 40 final val SIGNED = 63 - + final val firstInternalTag = 64 final val IMPLMETH = 64 @@ -322,6 +323,7 @@ object TastyFormat { final val PROTECTEDqualified = 105 final val RECtype = 106 final val SINGLETONtpt = 107 + final val LAZYref = 108 final val IDENT = 112 final val IDENTtpt = 113 @@ -512,6 +514,7 @@ object TastyFormat { case DOUBLEconst => "DOUBLEconst" case STRINGconst => "STRINGconst" case RECtype => "RECtype" + case LAZYref => "LAZYref" case IDENT => "IDENT" case IDENTtpt => "IDENTtpt" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 338a395ab685..885a76e3f763 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -246,6 +246,7 @@ class TreePickler(pickler: TastyPickler) { case tpe: ParamRef => assert(pickleParamRef(tpe), s"orphan parameter reference: $tpe") case tpe: LazyRef => + writeByte(LAZYref) pickleType(tpe.ref) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index d1f800c9926f..3015bef6d8e7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -293,6 +293,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi RecType(rt => registeringType(rt, readType())) case RECthis => RecThis(readTypeRef().asInstanceOf[RecType]) + case LAZYref => + val rdr = fork + skipTree() + LazyRef(implicit ctx => rdr.readType()) case SHARED => val ref = readAddr() typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType()) @@ -991,7 +995,12 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val refinements = readStats(refineCls, end)(localContext(refineCls)) RefinedTypeTree(parent, refinements, refineCls) case APPLIEDtpt => - AppliedTypeTree(readTpt(), until(end)(readTpt())) + // If we do directly a tpd.AppliedType tree we might get a + // wrong number of arguments in some scenarios reading F-bounded + // types. This came up in #137 of collection strawman. + val tycon = readTpt() + val args = until(end)(readTpt()) + untpd.AppliedTypeTree(tycon, args).withType(tycon.tpe.safeAppliedTo(args.tpes)) case ANDtpt => val tpt1 = readTpt() val tpt2 = readTpt() diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 3b398d23661c..757da5d83bc7 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -23,6 +23,7 @@ import dotty.tools.dotc.ast.Trees import dotty.tools.dotc.ast.untpd.Modifiers import dotty.tools.dotc.core.Flags.{FlagSet, Mutable} import dotty.tools.dotc.core.SymDenotations.SymDenotation +import scala.util.control.NonFatal object messages { @@ -708,10 +709,15 @@ object messages { private val actualArgString = actual.map(_.show).mkString("[", ", ", "]") - private val prettyName = fntpe.termSymbol match { - case NoSymbol => fntpe.show - case symbol => symbol.showFullName - } + private val prettyName = + try + fntpe.termSymbol match { + case NoSymbol => fntpe.show + case symbol => symbol.showFullName + } + catch { + case NonFatal(ex) => fntpe.show + } val msg = hl"""|${NoColor(msgPrefix)} type arguments for $prettyName$expectedArgString diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 72ce89a33942..130eb8d36754 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -249,7 +249,7 @@ object Checking { } catch { case ex: CyclicReference => ctx.debuglog(i"cycle detected for $tp, $nestedCycleOK, $cycleOK") - if (cycleOK) LazyRef(() => tp) + if (cycleOK) LazyRef(_ => tp) else if (reportErrors) throw ex else tp }