Skip to content
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

TypeTest of TypeBlock of Quotes API matches every Block #21721

Open
felher opened this issue Oct 7, 2024 · 0 comments · May be fixed by #21722
Open

TypeTest of TypeBlock of Quotes API matches every Block #21721

felher opened this issue Oct 7, 2024 · 0 comments · May be fixed by #21722
Labels
itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label

Comments

@felher
Copy link
Contributor

felher commented Oct 7, 2024

Compiler version

3.5.1 (and way before, as far as I can see)

Minimized code

Test.scala

object Test:
  // give a Block(...) to the macro
  Macro.impl:
    val a = 3
    a

Macro.scala

import quoted.*

object Macro:
  inline def impl(inline expr: Any): Any =
    ${implImpl('expr)}

  def implImpl(expr: Expr[Any])(using q: Quotes): Expr[Any] =
    import q.reflect.*
    expr.asTerm.asInstanceOf[Inlined].body match
      // this should not fail with a MatchError
      // but it does because `TypeBlock(_, _)` matches the block
      // of the `expr`, but of course `val a = ...` is not a `TypeDef`,
      // which the `unapply` of `TypeBlock` assumes.
      case TypeBlock(_, _) => '{ "TypeBlock" }
      case _ => '{ "Nothing" }

Output

[error] -- Error: /home/felher/tmp/macrotest/src/main/scala/Main.scala:3:4 -------------
[error] 2 |  Macro.impl:
[error] 3 |    val a = 3
[error]   |  ^
[error]   |Exception occurred while executing macro expansion.
[error]   |scala.MatchError: ValDef(a,TypeTree[TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Int)],Literal(Constant(3))) (of class dotty.tools.dotc.ast.Trees$ValDef)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl.scala$quoted$runtime$impl$QuotesImpl$reflect$TypeBlockMethods$$$_$aliases$$anonfun$1(QuotesImpl.scala:1431)
[error]   |	at scala.collection.immutable.List.map(List.scala:247)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeBlockMethods$.aliases(QuotesImpl.scala:1431)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeBlock$.unapply(QuotesImpl.scala:1426)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeBlock$.unapply(QuotesImpl.scala:1425)
[error]   |	at Macro$.implImpl(Impl.scala:10)
[error]   |
[error] 4 |    a 
[error]   |-----------------------------------------------------------------------------
[error]   |Inline stack trace
[error]   |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[error]   |This location contains code that was inlined from Impl.scala:5
[error] 5 |    ${implImpl('expr)}
[error]   |    ^^^^^^^^^^^^^^^^^^
[error]    -----------------------------------------------------------------------------
[error] one error found

Expectation

There should be no match error here. It should just compile fine.

PR

PR attempt for a fix here: #21722

@felher felher added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 7, 2024
felher added a commit to felher/dotty that referenced this issue Oct 7, 2024
TypeBlocks are represented as normal Blocks in the Quotes API. The
current TypeTest for TypeBlock is exactly the same as the TypeTest for
Block, which means that case TypeBlock(_, _) matches every block.

The implementation of unapply on TypeBlockModule, however, gives back
(List[TypeDef], TypeTree). It constructs the List[TypeDef] by mapping
over every statement, turning it into a TypeDef by using a match
with the pattern

  case alias: TypeDef => alias

Since the TypeTest matches any Block and not only Blocks that are
TypeBlocks, the statemnts can be anything, not just TypeDefs, which lets
the whole case TypeBlock(_, _) pattern fail with a MatchError.

This commit fixes the problem by making the TypeTest check whether the
Block is a type (which in turns checks whether the blocks expression is
a type)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant