Skip to content

Commit 4dc27d2

Browse files
authored
Merge pull request #2914 from dotty-staging/fix-cyclic-refs-strawman
Fix cyclic reference errors in collection strawman
2 parents 08087d8 + dd661bf commit 4dc27d2

File tree

7 files changed

+35
-18
lines changed

7 files changed

+35
-18
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ class TypeApplications(val self: Type) extends AnyVal {
443443
case dealiased: TypeBounds =>
444444
dealiased.derivedTypeBounds(dealiased.lo.appliedTo(args), dealiased.hi.appliedTo(args))
445445
case dealiased: LazyRef =>
446-
LazyRef(() => dealiased.ref.appliedTo(args))
446+
LazyRef(c => dealiased.ref(c).appliedTo(args))
447447
case dealiased: WildcardType =>
448448
WildcardType(dealiased.optBounds.appliedTo(args).bounds)
449449
case dealiased: TypeRef if dealiased.symbol == defn.NothingClass =>

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,25 +2149,23 @@ object Types {
21492149
}
21502150
}
21512151

2152-
case class LazyRef(private var refFn: () => Type) extends UncachedProxyType with ValueType {
2152+
case class LazyRef(private var refFn: Context => Type) extends UncachedProxyType with ValueType {
21532153
private var myRef: Type = null
21542154
private var computed = false
2155-
def ref = {
2155+
def ref(implicit ctx: Context) = {
21562156
if (computed) assert(myRef != null)
21572157
else {
21582158
computed = true
2159-
myRef = refFn()
2159+
myRef = refFn(ctx)
2160+
refFn = null
21602161
}
21612162
myRef
21622163
}
21632164
def evaluating = computed && myRef == null
21642165
override def underlying(implicit ctx: Context) = ref
2165-
override def toString = s"LazyRef($ref)"
2166-
override def equals(other: Any) = other match {
2167-
case other: LazyRef => this.ref.equals(other.ref)
2168-
case _ => false
2169-
}
2170-
override def hashCode = ref.hashCode + 37
2166+
override def toString = s"LazyRef(...)"
2167+
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
2168+
override def hashCode = System.identityHashCode(this)
21712169
}
21722170

21732171
// --- Refined Type and RecType ------------------------------------------------
@@ -3779,7 +3777,7 @@ object Types {
37793777
derivedSuperType(tp, this(thistp), this(supertp))
37803778

37813779
case tp: LazyRef =>
3782-
LazyRef(() => this(tp.ref))
3780+
LazyRef(_ => this(tp.ref))
37833781

37843782
case tp: ClassInfo =>
37853783
mapClassInfo(tp)

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ Standard-Section: "ASTs" TopLevelStat*
164164
BIND Length boundName_NameRef bounds_Type
165165
// for type-variables defined in a type pattern
166166
BYNAMEtype underlying_Type
167+
LAZYref underlying_Type
167168
POLYtype Length result_Type NamesTypes
168169
METHODtype Length result_Type NamesTypes // needed for refinements
169170
TYPELAMBDAtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing)
@@ -256,7 +257,7 @@ object TastyFormat {
256257
final val OBJECTCLASS = 40
257258

258259
final val SIGNED = 63
259-
260+
260261
final val firstInternalTag = 64
261262
final val IMPLMETH = 64
262263

@@ -322,6 +323,7 @@ object TastyFormat {
322323
final val PROTECTEDqualified = 105
323324
final val RECtype = 106
324325
final val SINGLETONtpt = 107
326+
final val LAZYref = 108
325327

326328
final val IDENT = 112
327329
final val IDENTtpt = 113
@@ -512,6 +514,7 @@ object TastyFormat {
512514
case DOUBLEconst => "DOUBLEconst"
513515
case STRINGconst => "STRINGconst"
514516
case RECtype => "RECtype"
517+
case LAZYref => "LAZYref"
515518

516519
case IDENT => "IDENT"
517520
case IDENTtpt => "IDENTtpt"

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ class TreePickler(pickler: TastyPickler) {
246246
case tpe: ParamRef =>
247247
assert(pickleParamRef(tpe), s"orphan parameter reference: $tpe")
248248
case tpe: LazyRef =>
249+
writeByte(LAZYref)
249250
pickleType(tpe.ref)
250251
}
251252

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi
293293
RecType(rt => registeringType(rt, readType()))
294294
case RECthis =>
295295
RecThis(readTypeRef().asInstanceOf[RecType])
296+
case LAZYref =>
297+
val rdr = fork
298+
skipTree()
299+
LazyRef(implicit ctx => rdr.readType())
296300
case SHARED =>
297301
val ref = readAddr()
298302
typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType())
@@ -991,7 +995,12 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi
991995
val refinements = readStats(refineCls, end)(localContext(refineCls))
992996
RefinedTypeTree(parent, refinements, refineCls)
993997
case APPLIEDtpt =>
994-
AppliedTypeTree(readTpt(), until(end)(readTpt()))
998+
// If we do directly a tpd.AppliedType tree we might get a
999+
// wrong number of arguments in some scenarios reading F-bounded
1000+
// types. This came up in #137 of collection strawman.
1001+
val tycon = readTpt()
1002+
val args = until(end)(readTpt())
1003+
untpd.AppliedTypeTree(tycon, args).withType(tycon.tpe.safeAppliedTo(args.tpes))
9951004
case ANDtpt =>
9961005
val tpt1 = readTpt()
9971006
val tpt2 = readTpt()

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import dotty.tools.dotc.ast.Trees
2323
import dotty.tools.dotc.ast.untpd.Modifiers
2424
import dotty.tools.dotc.core.Flags.{FlagSet, Mutable}
2525
import dotty.tools.dotc.core.SymDenotations.SymDenotation
26+
import scala.util.control.NonFatal
2627

2728
object messages {
2829

@@ -708,10 +709,15 @@ object messages {
708709

709710
private val actualArgString = actual.map(_.show).mkString("[", ", ", "]")
710711

711-
private val prettyName = fntpe.termSymbol match {
712-
case NoSymbol => fntpe.show
713-
case symbol => symbol.showFullName
714-
}
712+
private val prettyName =
713+
try
714+
fntpe.termSymbol match {
715+
case NoSymbol => fntpe.show
716+
case symbol => symbol.showFullName
717+
}
718+
catch {
719+
case NonFatal(ex) => fntpe.show
720+
}
715721

716722
val msg =
717723
hl"""|${NoColor(msgPrefix)} type arguments for $prettyName$expectedArgString

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ object Checking {
249249
} catch {
250250
case ex: CyclicReference =>
251251
ctx.debuglog(i"cycle detected for $tp, $nestedCycleOK, $cycleOK")
252-
if (cycleOK) LazyRef(() => tp)
252+
if (cycleOK) LazyRef(_ => tp)
253253
else if (reportErrors) throw ex
254254
else tp
255255
}

0 commit comments

Comments
 (0)