diff --git a/compiler/src/dotty/tools/dotc/inlines/Inliner.scala b/compiler/src/dotty/tools/dotc/inlines/Inliner.scala index 7c79e972c126..c1a1f7dbeb87 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inliner.scala @@ -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) diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index d6f962176ecc..f5db4565e801 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -67,6 +67,7 @@ mt-redux-norm.perspective.scala i18211.scala 10867.scala named-tuples1.scala +inline-match-opaque.scala # Opaque type i5720.scala diff --git a/tests/pos/inline-match-opaque-2.scala b/tests/pos/inline-match-opaque-2.scala new file mode 100644 index 000000000000..c0ea004a8a90 --- /dev/null +++ b/tests/pos/inline-match-opaque-2.scala @@ -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 diff --git a/tests/pos/inline-match-opaque.scala b/tests/pos/inline-match-opaque.scala new file mode 100644 index 000000000000..f4ed03542ff5 --- /dev/null +++ b/tests/pos/inline-match-opaque.scala @@ -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