-
Notifications
You must be signed in to change notification settings - Fork 1.9k
fix Macro error: expected Expr #19168 #21304
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a macro expansion bug (#19168) where AST-parsed metavariable fragments (like $t:ty) were being incorrectly stripped of invisible delimiters during transcription, causing individual tokens (e.g., 'static) to leak out and trigger "expected Expr" errors.
Key Changes:
- Introduced
TokensOriginenum to distinguish between raw token fragments and AST-parsed fragments - Updated
Fragment::Tokensfrom a tuple variant to a struct variant with anoriginfield - Modified matcher logic to tag fragments with appropriate origin during matching
- Updated transcriber to respect origin metadata and skip stripping invisible delimiters for AST-derived fragments
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
crates/mbe/src/expander.rs |
Adds TokensOrigin enum and converts Fragment::Tokens to struct variant with origin tracking |
crates/mbe/src/expander/matcher.rs |
Tags matched fragments with appropriate origin (Raw for ident/tt/lifetime/literal, Ast for ty/pat/stmt/block/meta/item/vis) |
crates/mbe/src/expander/transcriber.rs |
Conditionally applies strip_invisible() based on fragment origin during expansion |
crates/hir-def/src/macro_expansion_tests/mbe/regression.rs |
Adds regression test for ty fragment transcription preserving structure |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| enum TokensOrigin { | ||
| Raw, | ||
| Ast, | ||
| } |
Copilot
AI
Dec 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TokensOrigin enum should have documentation explaining the distinction between Raw and Ast variants. Consider adding a doc comment like:
/// Tracks whether token fragments come from raw tokens or parsed AST.
/// This distinction is important during transcription: AST-derived fragments
/// should not have their invisible delimiters stripped to preserve their
/// structure as complete syntactic units.
This would help future maintainers understand the purpose of this enum and when to use each variant.
| /// token fragments are just copy-pasted into the output | ||
| Tokens(tt::TokenTreesView<'a, Span>), | ||
| Tokens { | ||
| tree: tt::TokenTreesView<'a, Span>, | ||
| origin: TokensOrigin, | ||
| }, |
Copilot
AI
Dec 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation comment for the Tokens variant should be updated to explain the new origin field. The current comment "token fragments are just copy-pasted into the output" is incomplete. Consider updating it to:
/// Token fragments are transcribed into the output. The `origin` field tracks whether
/// these tokens come from raw input (ident/tt/lifetime/literal metavars) or parsed AST
/// (ty/pat/stmt/block/etc metavars). AST-derived fragments preserve their structure
/// during transcription by not stripping invisible delimiters.
This provides context for the new field and explains why it matters.
fix #19168
now tags every Fragment::Tokens with a TokensOrigin (raw token vs parsed AST) so we can keep track of which fragments need to stay wrapped as a single tt chunk during transcription.
records that ty/pat/pat_param/stmt/block/meta/item/vis metavars originate from AST parses while ident/tt/lifetime/literal stay raw, so bindings carry the right origin metadata from the moment they’re matched.
respects the new origin flag: ${concat} handling destructures the updated variant, and expand_var now leaves AST-derived fragments enclosed (preventing the stray 'static token that used to cause expected Expr), while raw fragments keep the previous strip-logic.
add test