Skip to content

Enhance constant-folding during inlining (second try)#25731

Open
mbovel wants to merge 2 commits intoscala:mainfrom
dotty-staging:mb/inline-val-constant
Open

Enhance constant-folding during inlining (second try)#25731
mbovel wants to merge 2 commits intoscala:mainfrom
dotty-staging:mb/inline-val-constant

Conversation

@mbovel
Copy link
Copy Markdown
Member

@mbovel mbovel commented Apr 8, 2026

#24431 was reverted in #25703. This PR attempts to restore the changes from #24431, with a single twist: we now “see through” ascriptions on if the type of the ascribed tree is indeed a subtype of the target type. This is rules out cases where the ascription is semantically required, as in #25703.

if res eq subTree then tree else res

tree match
case Typed(expr, _) if expr.tpe frozen_<:< tree.tpe => recChild(expr)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added guard is the single change compared to #24431.

@mbovel
Copy link
Copy Markdown
Member Author

mbovel commented Apr 8, 2026

Still failing (#25697):

-- Error: tests/pos-macros/i25697/Test_2.scala:7:19 --------------------------------------------------------------------
7 |  TinyMacro.inspect(pattern.matcher("value").matches())
  |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |  Exception occurred while executing macro expansion.
  |  scala.MatchError: Literal(Constant(6)) (of class dotty.tools.dotc.ast.Trees$Literal)
  |     at TinyMacro$.loop$1(Macro_1.scala:26)
  |     at TinyMacro$.TinyMacro$$$_$parseFlags$1(Macro_1.scala:28)
  |     at TinyMacro$given_FromExpr_Pattern$2$.unapply(Macro_1.scala:42)
  |     at scala.quoted.runtime.impl.QuotesImpl.valueOrAbort(QuotesImpl.scala:64)
  |     at TinyMacro$.inspectImpl(Macro_1.scala:47)
  |
  |---------------------------------------------------------------------------------------------------------------------
  |Inline stack trace
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |This location contains code that was inlined from Macro_1.scala:6
6 |  inline def inspect(inline expr: Boolean): Unit = ${ inspectImpl('expr) }
  |                                                   ^^^^^^^^^^^^^^^^^^^^^^^
   ---------------------------------------------------------------------------------------------------------------------

inlined at Test_2.scala:7:

Compilation failed for: 'tests/pos-macros/i25697'

https://github.com/scala/scala3/actions/runs/24135304347/job/70429540306#step:5:2382

I'll investigate, but it seems this is just a missing case in the user macro code.

@mbovel
Copy link
Copy Markdown
Member Author

mbovel commented Apr 8, 2026

The problem is that the library doesn't handle the case where Pattern.CASE_INSENSITIVE | Pattern.COMMENTS is constant-folded to 6. I think the library should handle it; I see no reason to assume it will not be constant-folded.

mbovel added a commit to mbovel/oolong that referenced this pull request Apr 8, 2026
When the compiler constant-folds `Pattern.CASE_INSENSITIVE | Pattern.COMMENTS`
into a single IntConstant (e.g. 6), parseFlags failed to match. This adds a
case to decompose the constant back into individual flag bits.

See scala/scala3#25731

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sjrd
Copy link
Copy Markdown
Member

sjrd commented Apr 8, 2026

An ascription that doesn't pass that condition is an invalid ascription. How does it even get there?

@mbovel
Copy link
Copy Markdown
Member Author

mbovel commented Apr 8, 2026

An ascription that doesn't pass that condition is an invalid ascription. How does it even get there?

It turns out you can generate malformed trees with macros. See #25690 for more 😅

@sjrd
Copy link
Copy Markdown
Member

sjrd commented Apr 8, 2026

Right. Then the macro needs to be fixed.

@mbovel
Copy link
Copy Markdown
Member Author

mbovel commented Apr 8, 2026

Right. Then the macro needs to be fixed.

Sure, that's why I opened the PR on ZIO to enable -Xcheck-macros and hopefully find the problem. But for now that just triggers another compiler crash.

In the meantime, and in case other codebases rely on broken macros, don't you think that defensively checking the assertion is valid would make sense?

@mbovel
Copy link
Copy Markdown
Member Author

mbovel commented Apr 8, 2026

See also the internal Slack discussion about -Xcheck-macros: https://lampepfl.slack.com/archives/C06FYNL1WDT/p1775647016206789.

@sjrd
Copy link
Copy Markdown
Member

sjrd commented Apr 8, 2026

don't you think that defensively checking the assertion is valid would make sense?

No, it really doesn't make sense. You can't pollute every other place of the compiler with dealing with bad stuff that macros generate. It's not sustainable. In this case it might run on the JVM because it inserts casts to heal things, but not on JS, whose backend is stricter.

At most, you could have a postprocessing after a macro that turns bad ascriptions into casts. And emits a warning in the process. At least the blast radius of that hack would be limited to macros.

@mbovel
Copy link
Copy Markdown
Member Author

mbovel commented Apr 8, 2026

I filled zio/zio#10721, let's see if I can get some help fixing this in ZIO directly.

danslapman pushed a commit to mbovel/oolong that referenced this pull request Apr 9, 2026
When the compiler constant-folds `Pattern.CASE_INSENSITIVE | Pattern.COMMENTS`
into a single IntConstant (e.g. 6), parseFlags failed to match. This adds a
case to decompose the constant back into individual flag bits.

See scala/scala3#25731

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
danslapman pushed a commit to mbovel/oolong that referenced this pull request Apr 9, 2026
When the compiler constant-folds `Pattern.CASE_INSENSITIVE | Pattern.COMMENTS`
into a single IntConstant (e.g. 6), parseFlags failed to match. This adds a
case to decompose the constant back into individual flag bits.

See scala/scala3#25731

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
danslapman pushed a commit to mbovel/oolong that referenced this pull request Apr 9, 2026
When the compiler constant-folds `Pattern.CASE_INSENSITIVE | Pattern.COMMENTS`
into a single IntConstant (e.g. 6), parseFlags failed to match. This adds a
case to decompose the constant back into individual flag bits.

See scala/scala3#25731

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
danslapman pushed a commit to leviysoft/oolong that referenced this pull request Apr 9, 2026
When the compiler constant-folds `Pattern.CASE_INSENSITIVE | Pattern.COMMENTS`
into a single IntConstant (e.g. 6), parseFlags failed to match. This adds a
case to decompose the constant back into individual flag bits.

See scala/scala3#25731

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants