@@ -1007,7 +1007,8 @@ object Types {
10071007 * pos/i536 demonstrates that the infinite loop can also involve lower bounds.
10081008 */
10091009 def safe_& (that : Type )(implicit ctx : Context ): Type = (this , that) match {
1010- case (TypeBounds (lo1, hi1), TypeBounds (lo2, hi2)) => TypeBounds (OrType (lo1, lo2), AndType (hi1, hi2))
1010+ case (TypeBounds (lo1, hi1), TypeBounds (lo2, hi2)) =>
1011+ TypeBounds (OrType (lo1.stripLazyRef, lo2.stripLazyRef), AndType (hi1.stripLazyRef, hi2.stripLazyRef))
10111012 case _ => this & that
10121013 }
10131014
@@ -1043,12 +1044,17 @@ object Types {
10431044 case _ => this
10441045 }
10451046
1046- /** Strip PolyType prefix */
1047+ /** Strip PolyType prefixes */
10471048 def stripPoly (implicit ctx : Context ): Type = this match {
10481049 case tp : PolyType => tp.resType.stripPoly
10491050 case _ => this
10501051 }
10511052
1053+ /** Strip LazyRef wrappers */
1054+ def stripLazyRef (given Context ): Type = this match
1055+ case lzy : LazyRef => lzy.ref.stripLazyRef
1056+ case _ => this
1057+
10521058 /** Widen from singleton type to its underlying non-singleton
10531059 * base type by applying one or more `underlying` dereferences,
10541060 * Also go from => T to T.
@@ -2566,25 +2572,34 @@ object Types {
25662572 }
25672573 }
25682574
2569- case class LazyRef (private var refFn : Context => Type ) extends UncachedProxyType with ValueType {
2575+ case class LazyRef (private var refFn : Context => Type , reportCycles : Boolean = false ) extends UncachedProxyType with ValueType {
25702576 private var myRef : Type = null
25712577 private var computed = false
2572- def ref (implicit ctx : Context ): Type = {
2573- if (computed) {
2574- if (myRef == null ) {
2578+
2579+ def ref (implicit ctx : Context ): Type =
2580+ if computed then
2581+ if myRef == null then
25752582 // if errors were reported previously handle this by throwing a CyclicReference
25762583 // instead of crashing immediately. A test case is neg/i6057.scala.
2577- assert(ctx.reporter.errorsReported)
2584+ assert(reportCycles || ctx.reporter.errorsReported)
25782585 throw CyclicReference (NoDenotation )
2579- }
2580- }
2581- else {
2586+ else
25822587 computed = true
2583- myRef = refFn(ctx)
2588+ val result = refFn(ctx)
25842589 refFn = null
2585- }
2590+ if result != null then myRef = result
2591+ else assert(myRef != null ) // must have been `update`d
25862592 myRef
2587- }
2593+
2594+ /** Update the value of the lazyref, discarding the compute function `refFn`
2595+ * Can be called only as long as the ref is still undefined.
2596+ */
2597+ def update (tp : Type ) =
2598+ assert(myRef == null )
2599+ myRef = tp
2600+ computed = true
2601+ refFn = null
2602+
25882603 def evaluating : Boolean = computed && myRef == null
25892604 def completed : Boolean = myRef != null
25902605 override def underlying (implicit ctx : Context ): Type = ref
@@ -4300,13 +4315,47 @@ object Types {
43004315 parentsCache
43014316 }
43024317
4318+ protected def newLikeThis (prefix : Type , classParents : List [Type ], decls : Scope , selfInfo : TypeOrSymbol )(given Context ): ClassInfo =
4319+ ClassInfo (prefix, cls, classParents, decls, selfInfo)
4320+
43034321 def derivedClassInfo (prefix : Type )(implicit ctx : Context ): ClassInfo =
43044322 if (prefix eq this .prefix) this
4305- else ClassInfo (prefix, cls , classParents, decls, selfInfo)
4323+ else newLikeThis (prefix, classParents, decls, selfInfo)
43064324
43074325 def derivedClassInfo (prefix : Type = this .prefix, classParents : List [Type ] = this .classParents, decls : Scope = this .decls, selfInfo : TypeOrSymbol = this .selfInfo)(implicit ctx : Context ): ClassInfo =
43084326 if ((prefix eq this .prefix) && (classParents eq this .classParents) && (decls eq this .decls) && (selfInfo eq this .selfInfo)) this
4309- else ClassInfo (prefix, cls, classParents, decls, selfInfo)
4327+ else newLikeThis(prefix, classParents, decls, selfInfo)
4328+
4329+ /** If this class has opaque type alias members, a new class info
4330+ * with their aliases added as refinements to the self type of the class.
4331+ * Otherwise, this classInfo.
4332+ * If there are opaque alias members, updates `cls` to have `Opaque` flag as a side effect.
4333+ */
4334+ def integrateOpaqueMembers (given Context ): ClassInfo =
4335+ decls.toList.foldLeft(this ) { (cinfo, sym) =>
4336+ if sym.isOpaqueAlias then
4337+ cls.setFlag(Opaque )
4338+ def force =
4339+ if sym.isOpaqueAlias then // could have been reset because of a syntax error
4340+ sym.infoOrCompleter match
4341+ case completer : LazyType =>
4342+ completer.complete(sym) // will update the LazyRef
4343+ null // tells the LazyRef to use the updated value
4344+ case info => // can occur under cyclic references, e.g. i6225.scala
4345+ defn.AnyType
4346+ else defn.AnyType // dummy type in case of errors
4347+ def refineSelfType (selfType : Type ) =
4348+ RefinedType (selfType, sym.name,
4349+ TypeAlias (LazyRef (_ => force, reportCycles = true )))
4350+ cinfo.selfInfo match
4351+ case self : Type =>
4352+ cinfo.derivedClassInfo(
4353+ selfInfo = refineSelfType(self.orElse(defn.AnyType )))
4354+ case self : Symbol =>
4355+ self.info = refineSelfType(self.info)
4356+ cinfo
4357+ else cinfo
4358+ }
43104359
43114360 override def computeHash (bs : Binders ): Int = doHash(bs, cls, prefix)
43124361 override def hashIsStable : Boolean = prefix.hashIsStable && classParents.hashIsStable
@@ -4343,13 +4392,12 @@ object Types {
43434392 final class TempClassInfo (prefix : Type , cls : ClassSymbol , decls : Scope , selfInfo : TypeOrSymbol )
43444393 extends CachedClassInfo (prefix, cls, Nil , decls, selfInfo) {
43454394
4346- /** Install classinfo with known parents in `denot` s */
4347- def finalize ( denot : SymDenotation , parents : List [Type ])(implicit ctx : Context ): Unit =
4348- denot.info = ClassInfo (prefix, cls, parents, decls, selfInfo)
4395+ /** Convert to classinfo with known parents */
4396+ def finalized ( parents : List [Type ])(implicit ctx : Context ): ClassInfo =
4397+ ClassInfo (prefix, cls, parents, decls, selfInfo)
43494398
4350- override def derivedClassInfo (prefix : Type )(implicit ctx : Context ): ClassInfo =
4351- if (prefix eq this .prefix) this
4352- else new TempClassInfo (prefix, cls, decls, selfInfo)
4399+ override def newLikeThis (prefix : Type , classParents : List [Type ], decls : Scope , selfInfo : TypeOrSymbol )(given Context ): ClassInfo =
4400+ TempClassInfo (prefix, cls, decls, selfInfo)
43534401
43544402 override def toString : String = s " TempClassInfo( $prefix, $cls) "
43554403 }
0 commit comments