From 4489e7ef1ec6213d7cf79bb576d1369da5fb8b52 Mon Sep 17 00:00:00 2001 From: Jan Chyb <48855024+jchyb@users.noreply.github.com> Date: Fri, 3 Jan 2025 19:59:53 +0100 Subject: [PATCH] Fix inline reduction for CaseDef guards with asInstanceOf (#22305) In Inliner.scala we add asInstanceOf to references to private inline methods to make sure we later are able to know which method is referenced (if e.g. we inline out of the scope where that method would be visible). This added asInstanceOf caused issue when inlining CaseDef guards, as instead of a simple constant literal we get an Inlined node with an added binding, like this: ```scala { val A_this: A = A_this.asInstanceOf[A] true:Boolean } ``` We fix that by just unpacking that Inlined node (and we do not need that binding for constant literals, so we can just ignore it). [Cherry-picked 1448123ce79ac96cc1de25ee84fd9a1fb063f3ba] --- .../dotty/tools/dotc/inlines/InlineReducer.scala | 2 +- tests/pos/i22300.scala | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i22300.scala diff --git a/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala b/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala index 1fa4fc624979..94755ea41c69 100644 --- a/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala +++ b/compiler/src/dotty/tools/dotc/inlines/InlineReducer.scala @@ -362,7 +362,7 @@ class InlineReducer(inliner: Inliner)(using Context): val (caseBindings, from, to) = substBindings(caseBindingMap.toList, mutable.ListBuffer(), Nil, Nil) val (guardOK, canReduceGuard) = if cdef.guard.isEmpty then (true, true) - else typer.typed(cdef.guard.subst(from, to), defn.BooleanType) match { + else stripInlined(typer.typed(cdef.guard.subst(from, to), defn.BooleanType)) match { case ConstantValue(v: Boolean) => (v, true) case _ => (false, false) } diff --git a/tests/pos/i22300.scala b/tests/pos/i22300.scala new file mode 100644 index 000000000000..156d913951b6 --- /dev/null +++ b/tests/pos/i22300.scala @@ -0,0 +1,16 @@ +class Foo: + + inline def inlineMatch[T]: String = + inline compiletime.erasedValue[T] match + case _: EmptyTuple => "" + case _: (h *: _) if checkType[h](0) => "" + + private inline def checkType[T](i: Int): Boolean = + inline compiletime.erasedValue[T] match + case _: Int => true + case _ => false + +val foo = Foo() + +@main def main () = + foo.inlineMatch[(Int, Boolean)]