diff --git a/compiler/src/dotty/tools/dotc/inlines/Inliner.scala b/compiler/src/dotty/tools/dotc/inlines/Inliner.scala index 92cae663352a..6a160b517326 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inliner.scala @@ -162,28 +162,9 @@ object Inliner: else Nil case _ => Nil val refinements = openOpaqueAliases(cls.givenSelfType) - - // Map references in the refinements from the proxied termRef - // to the recursive type of the refined type - // e.g.: Obj.type{type A = Obj.B; type B = Int} -> Obj.type{type A = .B; type B = Int} - def mapRecTermRefReferences(recType: RecType, refinedType: Type) = - new TypeMap { - def apply(tp: Type) = tp match - case RefinedType(a: RefinedType, b, info) => RefinedType(apply(a), b, apply(info)) - case RefinedType(a, b, info) => RefinedType(a, b, apply(info)) - case TypeRef(prefix, des) => TypeRef(apply(prefix), des) - case termRef: TermRef if termRef == ref => recType.recThis - case _ => mapOver(tp) - }.apply(refinedType) - val refinedType = refinements.foldLeft(ref: Type): (parent, refinement) => RefinedType(parent, refinement._1, TypeAlias(refinement._2)) - - val recType = RecType.closeOver ( recType => - mapRecTermRefReferences(recType, refinedType) - ) - - val refiningSym = newSym(InlineBinderName.fresh(), Synthetic, recType, span) + val refiningSym = newSym(InlineBinderName.fresh(), Synthetic, refinedType, span) refiningSym.termRef def unapply(refiningRef: TermRef)(using Context): Option[TermRef] = @@ -402,9 +383,6 @@ class Inliner(val call: tpd.Tree)(using Context): */ private val opaqueProxies = new mutable.ListBuffer[(TermRef, TermRef)] - /** TermRefs for which we already started synthesising proxies */ - private val visitedTermRefs = new mutable.HashSet[TermRef] - protected def hasOpaqueProxies = opaqueProxies.nonEmpty /** Map first halves of opaqueProxies pairs to second halves, using =:= as equality */ @@ -432,15 +410,12 @@ class Inliner(val call: tpd.Tree)(using Context): for cls <- ref.widen.baseClasses do if cls.containsOpaques && (forThisProxy || inlinedMethod.isContainedIn(cls)) - && !visitedTermRefs.contains(ref) + && mapRef(ref).isEmpty then - visitedTermRefs += ref val refiningRef = OpaqueProxy(ref, cls, call.span) val refiningSym = refiningRef.symbol.asTerm val refinedType = refiningRef.info - val refiningDef = addProxiesForRecurrentOpaques( - ValDef(refiningSym, tpd.ref(ref).cast(refinedType), inferred = true).withSpan(span) - ) + val refiningDef = ValDef(refiningSym, tpd.ref(ref).cast(refinedType), inferred = true).withSpan(span) inlining.println(i"add opaque alias proxy $refiningDef for $ref in $tp") bindingsBuf += refiningDef opaqueProxies += ((ref, refiningSym.termRef)) @@ -460,27 +435,6 @@ class Inliner(val call: tpd.Tree)(using Context): } ) - /** Transforms proxies that reference other opaque types, like for: - * object Obj1 { opaque type A = Int } - * object Obj2 { opaque type B = A } - * and proxy$1 of type Obj2.type{type B = Obj1.A} - * creates proxy$2 of type Obj1.type{type A = Int} - * and transforms proxy$1 into Obj2.type{type B = proxy$2.A} - */ - private def addProxiesForRecurrentOpaques(binding: ValDef)(using Context): ValDef = - def fixRefinedTypes(ref: Type): Unit = - ref match - case recType: RecType => fixRefinedTypes(recType.underlying) - case RefinedType(parent, name, info) => - addOpaqueProxies(info.widen, binding.span, true) - fixRefinedTypes(parent) - case _ => - fixRefinedTypes(binding.symbol.info) - binding.symbol.info = mapOpaques.typeMap(binding.symbol.info) - mapOpaques.transform(binding).asInstanceOf[ValDef] - .showing(i"transformed this binding exposing opaque aliases: $result", inlining) - end addProxiesForRecurrentOpaques - /** If `binding` contains TermRefs that refer to objects with opaque * type aliases, add proxy definitions that expose these aliases * and substitute such TermRefs with theproxies. Example from pos/opaque-inline1.scala: diff --git a/tests/pos/22359a.scala b/tests/pos/22359a.scala deleted file mode 100644 index a3b9ef63257a..000000000000 --- a/tests/pos/22359a.scala +++ /dev/null @@ -1,15 +0,0 @@ -opaque type NT[N <: Tuple, V <: Tuple] = V -opaque type System = NT[Tuple1["wires"], Tuple1[Any]] - -extension [N <: Tuple, V <: Tuple] (x: NT[N, V]) { - inline def apply(n: Int): Any = - x.productElement(n) -} - -extension (system: System) { - inline def foo = - system.apply(0) -} - -val simulation: System = ??? -val _ = simulation.foo diff --git a/tests/pos/22359b.scala b/tests/pos/22359b.scala deleted file mode 100644 index f6b7cbb462c1..000000000000 --- a/tests/pos/22359b.scala +++ /dev/null @@ -1,17 +0,0 @@ -object Obj2: - opaque type NT[N <: Tuple, V <: Tuple] = V - - extension [N <: Tuple, V <: Tuple] (x: NT[N, V]) { - inline def apply(n: Int): Any = - x.productElement(n) - } - -object Obj: - opaque type System = Obj2.NT[Tuple1["wires"], Tuple1[Any]] - - extension (system: System) { - inline def foo = system.apply(0) - } -import Obj._ -val simulation: System = ??? -val _ = simulation.foo diff --git a/tests/pos/i17243.scala b/tests/pos/i17243.scala deleted file mode 100644 index 3d42495b26b0..000000000000 --- a/tests/pos/i17243.scala +++ /dev/null @@ -1,17 +0,0 @@ -object Opaque: - opaque type A = Int - - val va: A = 1 - - inline def a(x: A) = - x + 1 - -object Opaque2: - opaque type B = Opaque.A - - val vb: B = Opaque.va - - inline def b(x: B) = Opaque.a(x) - -@main def Test() = - print(Opaque2.b(Opaque2.vb)) diff --git a/tests/pos/i22974a/Maybe_1.scala b/tests/pos/i22974a/Maybe_1.scala new file mode 100644 index 000000000000..bd4964b29582 --- /dev/null +++ b/tests/pos/i22974a/Maybe_1.scala @@ -0,0 +1,14 @@ +package pack +import Maybe._ +opaque type Maybe[+A] >: (Absent | Present[A]) = Absent | Present[A] +object Maybe: + sealed abstract class Absent + case object Absent extends Absent + object internal: + case class PresentAbsent(val depth: Int) + opaque type Present[+A] = A | internal.PresentAbsent + + extension [A](self: Maybe[A]) { + inline def flatten[B]: Maybe[B] = ??? + inline def isDefined: Boolean = ??? + } diff --git a/tests/pos/i22974a/macro_1.scala b/tests/pos/i22974a/macro_1.scala new file mode 100644 index 000000000000..61d7783bd38a --- /dev/null +++ b/tests/pos/i22974a/macro_1.scala @@ -0,0 +1,6 @@ +import scala.quoted._ + +inline def passThorugh(inline condition: Boolean): Any = + ${ passThorughImpl('{condition}) } + +def passThorughImpl(condition: Expr[Boolean])(using Quotes): Expr[Any] = condition diff --git a/tests/pos/i22974a/main_2.scala b/tests/pos/i22974a/main_2.scala new file mode 100644 index 000000000000..a0b55aff7f52 --- /dev/null +++ b/tests/pos/i22974a/main_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(): Unit = + import pack.Maybe + val res: Maybe[Maybe[Int]] = ??? + passThorugh(res.flatten.isDefined) +} diff --git a/tests/pos/i22974b.scala b/tests/pos/i22974b.scala new file mode 100644 index 000000000000..4f6e23c0f97d --- /dev/null +++ b/tests/pos/i22974b.scala @@ -0,0 +1,18 @@ +object outer: + opaque type Queue = Queue.Unsafe + object Queue: + abstract class Unsafe + opaque type Unbounded = Queue + object Unbounded: + inline def initWith()(f: Unbounded => Unit): Unit = + f(Unsafe.init()) + + opaque type Unsafe <: Queue.Unsafe = Queue + object Unsafe: + def init[A](): Unsafe = ??? + +object Resource: + def run: Unit = + outer.Queue.Unbounded.initWith() { q => + ??? + } diff --git a/tests/pos/i22974c.scala b/tests/pos/i22974c.scala new file mode 100644 index 000000000000..77833340de19 --- /dev/null +++ b/tests/pos/i22974c.scala @@ -0,0 +1,18 @@ +object other: + sealed abstract class Absent + case object Absent extends Absent + case class PresentAbsent(val depth: Int) + opaque type Present[+A] = A | PresentAbsent + opaque type Maybe[+A] >: (Absent | Present[A]) = Absent | Present[A] + + extension [A](self: Maybe[A]) { + inline def flatten[B]: Maybe[B] = if self.isEmpty then Absent else ??? + def isEmpty: Boolean = self.isInstanceOf[Absent] + } + +class Test { + def main(): Unit = + import other.Maybe + val res: Maybe[Maybe[Int]] = ??? + res.flatten +}