feat: auto-detect imperative for/while/loop in preamble#4146
Open
Madoshakalaka wants to merge 2 commits intomasterfrom
Open
feat: auto-detect imperative for/while/loop in preamble#4146Madoshakalaka wants to merge 2 commits intomasterfrom
Madoshakalaka wants to merge 2 commits intomasterfrom
Conversation
When a fork-parsed `Stmt::Expr(For/While/Loop, None)` succeeds, the entire expression is Rust-parseable and contains no html elements, so it cannot be a misread of html-control-flow. Accept it as a preamble statement instead of erroring with the `let _ = ...;` hint. Users no longer need a trailing `;` or a `let _ =` binding to use imperative side-effect loops inside an html! body.
|
Visit the preview URL for this PR (updated for commit e611fb0): https://yew-rs--pr4146-auto-imperative-prea-6fnzvy2o.web.app (expires Thu, 07 May 2026 08:14:06 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 |
Benchmark - coreYew MasterPull Request |
Size ComparisonDetails
✅ None of the examples has changed their size significantly. |
Benchmark - SSRYew MasterDetails
Pull RequestDetails
|
Member
Author
|
e611fb0 adds caution and workarounds on the website for this slightly relevant footgun pattern: html! {
if condition {
for _ in 0..10 {
{my_foo}
}
}
}When a user writes this. They probally want to render |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
First off, the final diagnostics patch in b9fe62a in #4124 seems unnecessary. Either
let _ = for {...}or a trailing comma (for {...};) seems to do the same job and the latter should have definitely be recommended. I mistakenly thoughtlet _ =was the only workaround in some edge cases, tried various patterns today and can't really reproduce.This PR should finally remove the need for all these temporary workarounds though.
This PR now auto-detects imperative
for/while/loopblocks inhtml!preamble position so users no longer need a trailing;or alet _ =binding to make them parse as Rust statements.Details
Before, this was an error:
The inner
forparses asStmt::Expr(ForLoop, None)and used to be rejected with a help message pointing atlet _ = ...;. The reason the parser was conservative: a bare imperative loop in preamble looks identical to html-for-control-flow with a body that has no html children. The two interpretations are indistinguishable on syntax alone.But they are not indistinguishable in practice. If syn can fully parse the loop as a Rust
Stmt, the entire expression contains no html elements anywhere inside, and an html-forover an html-less body would just emit emptyVLists per iteration which is rarely what anyone wants. So we accept it as a Rust statement instead.When the body does contain html, syn fails to parse it as
Stmtand we fall through to the html-control-flow parser exactly as before.if/match/bare-{...}are unchanged.The trailing-
;andlet _ = ...;forms still work as regression patterns.Checklist
packages/yew-macro/tests/html_macro/imperative-preamble-pass.rs(new): mirrors the deletedimperative-preamble-fail.rs, plus labeled-loop and back-to-back loop coverage.packages/yew/tests/html_for.rs: three new wasm tests asserting the inner-loop side effects run and that the surrounding html-for emits one node per outer iteration (for_imperative_inner_for_runs_as_preamble,..._while_...,..._loop_...).packages/yew-macro/tests/html_macro/for-pass.rs: regression cases proving the trailing-;andlet _ = ...;forms still parse.imperative-preamble-fail.{rs,stderr}since the cases now compile cleanly.