-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Unable to match a lower-case constructor in quoted pattern #22616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I don't know the details, but a recent conversation about annotation includes #22553 |
I can have a look; @Gedochao can we assign this to me for this cycle? |
Thanks @mbovel! |
I guess, generally it would be nice if the compiler provided a built-in mechanism for deriving |
The problem does not seem linked to annotations or classes extending annotations. It seems to be linked to classes with lower-case names. Compiles successfully: import scala.quoted.{Expr, Quotes}
class Foo(name: String) extends scala.annotation.StaticAnnotation
object Macro:
inline def myMacro3(): Unit =
${ myMacroImpl3('{new Foo("hello")}) }
def myMacroImpl3(x: Expr[Foo])(using q: Quotes): Expr[Unit] =
x match
case '{new Foo(${Expr(name)})} =>
println(name)
case _ =>
println("not a Foo")
'{()} $ scala compile --server=false -S 3.6.3 22616
hello Errors out: import scala.quoted.{FromExpr, Expr, Quotes}
class foo(name: String)
object Macro:
inline def myMacro3(): Unit =
${ myMacroImpl3('{new foo("hello")}) }
def myMacroImpl3(x: Expr[foo])(using q: Quotes): Expr[Unit] =
x match
case '{new foo(${Expr(name)})} =>
println(name)
case _ =>
println("not a foo")
'{()} $ scala compile --server=false -S 3.6.3 22616
-- Error: /localhome/bovel/scala3/22616/defs.scala:11:17 -------------------------------------------------------------------------------------------------------------------------
11 | case '{new foo(${Expr(name)})} =>
| ^^^
| foo does not have a constructor
-- Error: /localhome/bovel/scala3/22616/defs.scala:11:27 -------------------------------------------------------------------------------------------------------------------------
11 | case '{new foo(${Expr(name)})} =>
| ^^^^^^^^^^
| Type must be fully defined.
| Consider annotating the splice using a type ascription:
| (${Expr(name)}: XYZ).
-- [E006] Not Found Error: /localhome/bovel/scala3/22616/defs.scala:12:16 --------------------------------------------------------------------------------------------------------
12 | println(name)
| ^^^^
| Not found: name - did you mean Some?
|
| longer explanation available when compiling with `-explain`
3 errors found
Compilation failed $ scala compile -Ydebug-error --server=false -S 3.6.3 22616
-- Error: /localhome/bovel/scala3/22616/defs.scala:11:17 -------------------------------------------------------------------------------------------------------------------------
11 | case '{new foo(${Expr(name)})} =>
| ^^^
| foo does not have a constructor
java.lang.Exception: Stack trace
at java.base/java.lang.Thread.dumpStack(Thread.java:1389)
at dotty.tools.dotc.report$.error(report.scala:70)
at dotty.tools.dotc.typer.ErrorReporting$.errorType(ErrorReporting.scala:32)
at dotty.tools.dotc.typer.TypeAssigner.notAMemberErrorType(TypeAssigner.scala:186)
at dotty.tools.dotc.typer.TypeAssigner.notAMemberErrorType$(TypeAssigner.scala:16)
at dotty.tools.dotc.typer.Typer.notAMemberErrorType(Typer.scala:148)
at dotty.tools.dotc.typer.Typer.reportAnError$1(Typer.scala:897)
at dotty.tools.dotc.typer.Typer.typedSelectWithAdapt(Typer.scala:911)
at dotty.tools.dotc.typer.Typer.typeSelectOnTerm$1(Typer.scala:996)
at dotty.tools.dotc.typer.Typer.typedSelect(Typer.scala:1034)
at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3475)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3584)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3666)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3777)
at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:1051)
at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:1244)
at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:434)
at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:148)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3500)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3585)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3666)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3777)
at dotty.tools.dotc.typer.QuotesAndSplices.typedQuotePattern(QuotesAndSplices.scala:286)
at dotty.tools.dotc.typer.QuotesAndSplices.typedQuote(QuotesAndSplices.scala:56)
at dotty.tools.dotc.typer.QuotesAndSplices.typedQuote$(QuotesAndSplices.scala:32) |
Adding backticks enables the lower case version to compile as expected: def myMacroImpl3(x: Expr[foo])(using q: Quotes): Expr[Unit] =
x match
case '{new `foo`($name)} =>
println(name)
case _ =>
println("not a foo") |
I am not sure if the current behavior is expected or is a bug; I can't find a definitive answer in the documentation. In general, what do lower case identifiers in term positions in quoted patterns mean? I see I can match Somehow related: this page says that lower case identifiers in type positions are binders: “Just as in a normal pattern, the type variables are written using lower case names.” |
Further thinking about it, I think this is a bug, and that the culprit is this condition in
The condition is true when typing |
I agree it looks like a bug (especially with that error message). I also believe the type positions part in |
That would make sense to me. Unfortunately, I don't think we can easily know if we are in one of these nodes when typing the nested identifier. At least, mode and prototype do not help:
|
It might actually only be inside
And that even seems to be too general; for example, this doesn't compile: import scala.quoted.{FromExpr, Expr, Quotes}
case class Foo[T](x: String)
object Macro:
inline def myMacro3(): Unit =
${ myMacroImpl3('{Foo[Any]("hello")}) }
def myMacroImpl3(x: Expr[Foo[Any]])(using Quotes): Expr[Unit] =
x match
case '{ Foo($y: t) } =>
'{Foo[t]($y); ()}
case _ =>
println("not a foo")
'{()} -- [E007] Type Mismatch Error: test.scala:11:18 --------------------------------
11 | case '{ Foo($y: t) } =>
| ^^^^^
| Found: t
| Required: String
|
| longer explanation available when compiling with `-explain`
Set()
-- [E006] Not Found Error: test.scala:12:14 ------------------------------------
12 | '{Foo[t]($y); ()}
| ^
| Not found: type t
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: test.scala:12:18 ------------------------------------
12 | '{Foo[t]($y); ()}
| ^
| Not found: y
|
| longer explanation available when compiling with `-explain`
3 errors found But it does if the field |
Compiler version
3.6.3
Minimized code
Output
then add a case for that in the
FromExpr
, and...Expectation
That either:
case '{ caseName(${ Expr(name) }) } => caseName(name).some
matchescase '{ new caseName(${ Expr(name) }) } => caseName(name).some
is allowed, and matchesQuite difficult to handle when you see "we found this, but cant match on it", and then when you try to match
on the exact expr.show
, it says that expr is not valid?The text was updated successfully, but these errors were encountered: