@@ -144,9 +144,28 @@ object Inliner:
144
144
else Nil
145
145
case _ => Nil
146
146
val refinements = openOpaqueAliases(cls.givenSelfType)
147
+
148
+ // Map references in the refinements from the proxied termRef
149
+ // to the recursive type of the refined type
150
+ // e.g.: Obj.type{type A = Obj.B; type B = Int} -> Obj.type{type A = <recthis>.B; type B = Int}
151
+ def mapRecTermRefReferences (recType : RecType , refinedType : Type ) =
152
+ new TypeMap {
153
+ def apply (tp : Type ) = tp match
154
+ case RefinedType (a : RefinedType , b, info) => RefinedType (apply(a), b, apply(info))
155
+ case RefinedType (a, b, info) => RefinedType (a, b, apply(info))
156
+ case TypeRef (prefix, des) => TypeRef (apply(prefix), des)
157
+ case termRef : TermRef if termRef == ref => recType.recThis
158
+ case _ => mapOver(tp)
159
+ }.apply(refinedType)
160
+
147
161
val refinedType = refinements.foldLeft(ref : Type ): (parent, refinement) =>
148
162
RefinedType (parent, refinement._1, TypeAlias (refinement._2))
149
- val refiningSym = newSym(InlineBinderName .fresh(), Synthetic , refinedType, span)
163
+
164
+ val recType = RecType .closeOver ( recType =>
165
+ mapRecTermRefReferences(recType, refinedType)
166
+ )
167
+
168
+ val refiningSym = newSym(InlineBinderName .fresh(), Synthetic , recType, span)
150
169
refiningSym.termRef
151
170
152
171
def unapply (refiningRef : TermRef )(using Context ): Option [TermRef ] =
@@ -387,7 +406,9 @@ class Inliner(val call: tpd.Tree)(using Context):
387
406
val refiningRef = OpaqueProxy (ref, cls, call.span)
388
407
val refiningSym = refiningRef.symbol.asTerm
389
408
val refinedType = refiningRef.info
390
- val refiningDef = ValDef (refiningSym, tpd.ref(ref).cast(refinedType), inferred = true ).withSpan(span)
409
+ val refiningDef = addProxiesForRecurrentOpaques(
410
+ ValDef (refiningSym, tpd.ref(ref).cast(refinedType), inferred = true ).withSpan(span)
411
+ )
391
412
inlining.println(i " add opaque alias proxy $refiningDef for $ref in $tp" )
392
413
bindingsBuf += refiningDef
393
414
opaqueProxies += ((ref, refiningSym.termRef))
@@ -407,6 +428,27 @@ class Inliner(val call: tpd.Tree)(using Context):
407
428
}
408
429
)
409
430
431
+ /** Transforms proxies that reference other opaque types, like for:
432
+ * object Obj1 { opaque type A = Int }
433
+ * object Obj2 { opaque type B = A }
434
+ * and proxy$1 of type Obj2.type{type B = Obj1.A}
435
+ * creates proxy$2 of type Obj1.type{type A = Int}
436
+ * and transforms proxy$1 into Obj2.type{type B = proxy$2.A}
437
+ */
438
+ private def addProxiesForRecurrentOpaques (binding : ValDef )(using Context ): ValDef =
439
+ def fixRefinedTypes (ref : Type ): Unit =
440
+ ref match
441
+ case recType : RecType => fixRefinedTypes(recType.underlying)
442
+ case RefinedType (parent, name, info) =>
443
+ addOpaqueProxies(info.widen, binding.span, true )
444
+ fixRefinedTypes(parent)
445
+ case _ =>
446
+ fixRefinedTypes(binding.symbol.info)
447
+ binding.symbol.info = mapOpaques.typeMap(binding.symbol.info)
448
+ mapOpaques.transform(binding).asInstanceOf [ValDef ]
449
+ .showing(i " transformed this binding exposing opaque aliases: $result" , inlining)
450
+ end addProxiesForRecurrentOpaques
451
+
410
452
/** If `binding` contains TermRefs that refer to objects with opaque
411
453
* type aliases, add proxy definitions that expose these aliases
412
454
* and substitute such TermRefs with theproxies. Example from pos/opaque-inline1.scala:
0 commit comments