Skip to content

Commit

Permalink
Fix stack overflow errors when generating opaque type proxies (#22479)
Browse files Browse the repository at this point in the history
Before the regressive PR, we would check via the generated opaqueProxies
list whether one was already generated. In that PR, we tried allowing
generating proxies for rhs of currently generated proxy. Since we have
to add the generated proxy to opaqueProxies only after that step, this
could cause infinite recursion (and adding the proxies earlier could
cause another infinite loop).

To fix that, we add another collection for termrefs which we already
visited this way, but which is not used in the `mapOpaques` function.
  • Loading branch information
jchyb authored Jan 30, 2025
1 parent 4ab5c5d commit 6d9b0f1
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/inlines/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ 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 */
Expand All @@ -401,8 +404,9 @@ class Inliner(val call: tpd.Tree)(using Context):
for cls <- ref.widen.baseClasses do
if cls.containsOpaques
&& (forThisProxy || inlinedMethod.isContainedIn(cls))
&& mapRef(ref).isEmpty
&& !visitedTermRefs.contains(ref)
then
visitedTermRefs += ref
val refiningRef = OpaqueProxy(ref, cls, call.span)
val refiningSym = refiningRef.symbol.asTerm
val refinedType = refiningRef.info
Expand Down
10 changes: 10 additions & 0 deletions tests/pos/i22468.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Result.*
opaque type Result[+E, +A] = Success[A] | Error[E]

object Result:
opaque type Success[+A] = A
sealed abstract class Error[+E]

extension [E, A](self: Result[E, A])
inline def transform[B]: B = ???
def problem: Boolean = transform[Boolean]

0 comments on commit 6d9b0f1

Please sign in to comment.