Skip to content

Commit

Permalink
Reduce some match type in inlining to avoid opaque type headaches
Browse files Browse the repository at this point in the history
The inliner tries to handle opaque types by replacing prefixes containing them
by proxy objects with type aliases. When the type we're mapping is a match type
application, this can end up breaking its reduction.

Reducing match type applications instead of performing this mapping seems to
avoid the issue in practice, but I don't know if it completely solves the
problem.

Fixes scala#20427.
  • Loading branch information
smarter committed May 22, 2024
1 parent 7d559ad commit ff2d53f
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 0 deletions.
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/inlines/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@ class Inliner(val call: tpd.Tree)(using Context):
private val mapOpaques = TreeTypeMap(
typeMap = new TypeMap:
override def stopAt = StopAt.Package
override protected def derivedAppliedType(tp: AppliedType, tycon: Type, args: List[Type]): Type =
if (args ne tp.args) && tp.isMatchAlias && tp.tryNormalize.exists then
// #20427: A match type with mapped arguments might fail to reduce
// (narrowing doesn't hold for match types), so prefer reducing
// them if possible.
apply(tp.normalized)
else super.derivedAppliedType(tp, tycon, args)
def apply(t: Type) = mapOver {
t match
case ref: TermRef => mapRef(ref).getOrElse(ref)
Expand Down
1 change: 1 addition & 0 deletions compiler/test/dotc/pos-test-pickling.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ mt-redux-norm.perspective.scala
i18211.scala
10867.scala
named-tuples1.scala
inline-match-opaque.scala

# Opaque type
i5720.scala
Expand Down
6 changes: 6 additions & 0 deletions tests/pos/inline-match-opaque-2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.language.experimental.namedTuples

object Test:
type NT = NamedTuple.Concat[(hi: Int), (bla: String)]
def foo(x: NT) =
x.hi // error
19 changes: 19 additions & 0 deletions tests/pos/inline-match-opaque.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
object Foo:
opaque type Wrapper[T] = T
def part[T](w: Wrapper[T]): T = w
inline def part2[T](w: Wrapper[T]): T = part(w) //part(w.asInstanceOf[Wrapper[T]]) also fixes the issue
type Rewrap[W] = Wrapper[Extra.Unwrap[W]]

object Extra:
type Unwrap[W] = W match
case Foo.Wrapper[t] => t
type Rewrap[W] = Foo.Wrapper[Unwrap[W]]

object Test:
type X = Extra.Rewrap[Foo.Wrapper[Int]]
def foo1(x: Foo.Wrapper[Extra.Unwrap[Foo.Wrapper[Int]]]) =
Foo.part(x) // ok
Foo.part2(x) // ok
def foo2(x: X) =
Foo.part(x) // ok
Foo.part2(x) // error

0 comments on commit ff2d53f

Please sign in to comment.