From 3daa4e7bf7a9d7b64ed66135bbaa955f85fe98eb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 13 Jul 2023 10:28:56 +0200 Subject: [PATCH] Do not eta-expand pattern splices with contextual function types Fixes #18197 --- .../src/dotty/tools/dotc/typer/Typer.scala | 4 +++- tests/pos-macros/i18197a.scala | 7 +++++++ tests/pos-macros/i18197b/Macro.scala | 18 ++++++++++++++++++ tests/pos-macros/i18197b/Test.scala | 19 +++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i18197a.scala create mode 100644 tests/pos-macros/i18197b/Macro.scala create mode 100644 tests/pos-macros/i18197b/Test.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ee8aa668296d..13b7aeb1603b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3173,6 +3173,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer && xtree.isTerm && !untpd.isContextualClosure(xtree) && !ctx.mode.is(Mode.Pattern) + && !xtree.isInstanceOf[SplicePattern] && !ctx.isAfterTyper && !ctx.isInlineContext then @@ -3957,7 +3958,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer sym.isConstructor || sym.matchNullaryLoosely || Feature.warnOnMigration(msg, tree.srcPos, version = `3.0`) - && { + && { msg.actions .headOption .foreach(Rewrites.applyAction) @@ -4021,6 +4022,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer && pt != SingletonTypeProto && pt != AssignProto && !ctx.mode.is(Mode.Pattern) + && !tree.isInstanceOf[SplicePattern] && !ctx.isAfterTyper && !ctx.isInlineContext then diff --git a/tests/pos-macros/i18197a.scala b/tests/pos-macros/i18197a.scala new file mode 100644 index 000000000000..05c997158cf8 --- /dev/null +++ b/tests/pos-macros/i18197a.scala @@ -0,0 +1,7 @@ +import scala.quoted.* + +def readPathMacro[A: Type, B: Type](expr: Expr[Any])(using Quotes) = + expr match + case '{ foo($y) } => y: Expr[Int ?=> Int] + +def foo(x: Int ?=> Int): Any = ??? diff --git a/tests/pos-macros/i18197b/Macro.scala b/tests/pos-macros/i18197b/Macro.scala new file mode 100644 index 000000000000..9afe96a6d74c --- /dev/null +++ b/tests/pos-macros/i18197b/Macro.scala @@ -0,0 +1,18 @@ +import scala.quoted.* + +object ReproMacro { + inline def readPath[A, B](inline config: Config[A, B]) = ${ readPathMacro[A, B]('config) } + + def readPathMacro[A: Type, B: Type](expr: Expr[Config[A, B]])(using Quotes) = { + import quotes.reflect.report + + expr match { + case '{ Field.const[a, b, tpe]($selector) } => + val selector2: Expr[Selector ?=> a => tpe] = selector + report.info(s"Matched!") + '{} + case other => + report.errorAndAbort("woops, I did not match") + } + } +} diff --git a/tests/pos-macros/i18197b/Test.scala b/tests/pos-macros/i18197b/Test.scala new file mode 100644 index 000000000000..908e58cf3e94 --- /dev/null +++ b/tests/pos-macros/i18197b/Test.scala @@ -0,0 +1,19 @@ +trait Selector { + extension [A](self: A) def at[B <: A]: B +} + +trait Config[A, B] + +object Field { + def const[A, B, FieldTpe](selector: Selector ?=> A => FieldTpe): Config[A, B] = ??? +} + +final case class Example(int: Int) + +@main def main = { + // compiles just fine + ReproMacro.readPath[Example, Example](Field.const(_.int)) + + // doesn't compile + ReproMacro.readPath[Example, Example](Field.const(_.int.at[Int])) +}