Parenthesize or-patterns in prefix pattern positions in pretty printer#154085
Merged
rust-bors[bot] merged 2 commits intorust-lang:mainfrom Mar 23, 2026
Merged
Parenthesize or-patterns in prefix pattern positions in pretty printer#154085rust-bors[bot] merged 2 commits intorust-lang:mainfrom
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
Conversation
Collaborator
|
r? @chenyukang rustbot has assigned @chenyukang. Use Why was this reviewer chosen?The reviewer was selected based on:
|
The AST pretty printer was dropping parentheses around or-patterns
when they appeared inside `@` bindings, `&` references, or `box`
patterns. For example:
- `v @ (1 | 2 | 3)` was printed as `v @ 1 | 2 | 3`
- `&(1 | 2 | 3)` was printed as `&1 | 2 | 3`
- `box (1 | 2 | 3)` was printed as `box 1 | 2 | 3`
Since `|` has the lowest precedence among pattern operators, all of
these are parsed incorrectly without parentheses — e.g. `v @ 1 | 2 | 3`
becomes `(v @ 1) | 2 | 3`, binding `v` only to the first alternative.
This caused E0408 ("variable not bound in all patterns") when the
expanded output was fed back to the compiler, affecting crates like
html5ever and wgpu-core that use macros expanding to or-patterns
after `@`.
The fix adds a `print_pat_paren_if_or` helper that wraps `PatKind::Or`
subpatterns in parentheses, and uses it in the `@`, `&`, and `box`
printing arms. This is similar in spirit to the existing `FixupContext`
parenthesization approach used for expression printing.
Signed-off-by: Andrew V. Teylu <andrew.teylu@vector.com>
d880685 to
e15897f
Compare
This comment has been minimized.
This comment has been minimized.
The pretty printer now correctly parenthesizes or-patterns inside `box` patterns, which changes the Clippy `unnested_or_patterns` lint suggestion from `box box (0 | 2 | 4)` to `box (box (0 | 2 | 4))`. The new output is more correct — the old suggestion was itself missing parens and would have been parsed as `box (box 0) | 2 | 4`. Signed-off-by: Andrew V. Teylu <andrew.teylu@vector.com>
Collaborator
|
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
Member
|
@bors r=chenyukang |
Contributor
JonathanBrouwer
added a commit
to JonathanBrouwer/rust
that referenced
this pull request
Mar 23, 2026
…chenyukang
Parenthesize or-patterns in prefix pattern positions in pretty printer
The AST pretty printer was dropping parentheses around or-patterns when they appeared inside `@` bindings, `&` references, or `box` patterns. For example:
- `v @ (1 | 2 | 3)` was printed as `v @ 1 | 2 | 3`
- `&(1 | 2 | 3)` was printed as `&1 | 2 | 3`
- `box (1 | 2 | 3)` was printed as `box 1 | 2 | 3`
Since `|` has the lowest precedence among pattern operators, all of these are parsed incorrectly without parentheses — e.g. `v @ 1 | 2 | 3` becomes `(v @ 1) | 2 | 3`, binding `v` only to the first alternative.
This caused E0408 ("variable not bound in all patterns") when the expanded output was fed back to the compiler, affecting crates like html5ever and wgpu-core that use macros expanding to or-patterns after `@`.
The fix adds a `print_pat_paren_if_or` helper that wraps `PatKind::Or` subpatterns in parentheses, and uses it in the `@`, `&`, and `box` printing arms. This is similar in spirit to the existing `FixupContext` parenthesization approach used for expression printing.
## Example
**before** (`rustc 1.96.0-nightly (3b1b0ef 2026-03-11)`):
```rust
#![feature(prelude_import)]
#![no_std]
#![feature(box_patterns)]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-compare-only
//@ pretty-mode:expanded
//@ pp-exact:or-pattern-paren.pp
macro_rules! or_pat { ($($name:pat),+) => { $($name)|+ } }
fn check_at(x: Option<i32>) {
match x {
Some(v @ 1 | 2 | 3) =>
{
::std::io::_print(format_args!("{0}\n", v));
}
_ => {}
}
}
fn check_ref(x: &i32) { match x { &1 | 2 | 3 => {} _ => {} } }
fn check_box(x: Box<i32>) { match x { box 1 | 2 | 3 => {} _ => {} } }
fn main() { check_at(Some(2)); check_ref(&1); check_box(Box::new(1)); }
```
**after** (this branch):
```rust
#![feature(prelude_import)]
#![no_std]
#![feature(box_patterns)]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-compare-only
//@ pretty-mode:expanded
//@ pp-exact:or-pattern-paren.pp
macro_rules! or_pat { ($($name:pat),+) => { $($name)|+ } }
fn check_at(x: Option<i32>) {
match x {
Some(v @ (1 | 2 | 3)) =>
{
::std::io::_print(format_args!("{0}\n", v));
}
_ => {}
}
}
fn check_ref(x: &i32) { match x { &(1 | 2 | 3) => {} _ => {} } }
fn check_box(x: Box<i32>) { match x { box (1 | 2 | 3) => {} _ => {} } }
fn main() { check_at(Some(2)); check_ref(&1); check_box(Box::new(1)); }
```
Notice `v @ 1 | 2 | 3` becomes `v @ (1 | 2 | 3)`, `&1 | 2 | 3` becomes `&(1 | 2 | 3)`, and `box 1 | 2 | 3` becomes `box (1 | 2 | 3)`. Without parens, the or-pattern binds incorrectly — only the first alternative gets the `@`/`&`/`box`, causing E0408.
This was referenced Mar 23, 2026
rust-bors bot
pushed a commit
that referenced
this pull request
Mar 23, 2026
…uwer Rollup of 13 pull requests Successful merges: - #154241 (`rust-analyzer` subtree update) - #153686 (`std`: include `dlmalloc` for all non-wasi Wasm targets) - #154105 (bootstrap: Pass `--features=rustc` to rustc_transmute) - #153069 ([BPF] add target feature allows-misaligned-mem-access) - #154085 (Parenthesize or-patterns in prefix pattern positions in pretty printer) - #154191 (refactor RangeFromIter overflow-checks impl) - #154207 (Refactor query loading) - #153540 (drop derive helpers during attribute parsing) - #154140 (Document consteval behavior of ub_checks, overflow_checks, is_val_statically_known.) - #154161 (On E0277 tweak help when single type impls traits) - #154218 (interpret/validity: remove unreachable error kind) - #154225 (diagnostics: avoid ICE in confusable_method_name for associated functions) - #154228 (Improve inline assembly error messages)
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.
The AST pretty printer was dropping parentheses around or-patterns when they appeared inside
@bindings,&references, orboxpatterns. For example:v @ (1 | 2 | 3)was printed asv @ 1 | 2 | 3&(1 | 2 | 3)was printed as&1 | 2 | 3box (1 | 2 | 3)was printed asbox 1 | 2 | 3Since
|has the lowest precedence among pattern operators, all of these are parsed incorrectly without parentheses — e.g.v @ 1 | 2 | 3becomes(v @ 1) | 2 | 3, bindingvonly to the first alternative.This caused E0408 ("variable not bound in all patterns") when the expanded output was fed back to the compiler, affecting crates like html5ever and wgpu-core that use macros expanding to or-patterns after
@.The fix adds a
print_pat_paren_if_orhelper that wrapsPatKind::Orsubpatterns in parentheses, and uses it in the@,&, andboxprinting arms. This is similar in spirit to the existingFixupContextparenthesization approach used for expression printing.Example
before (
rustc 1.96.0-nightly (3b1b0ef4d 2026-03-11)):after (this branch):
Notice
v @ 1 | 2 | 3becomesv @ (1 | 2 | 3),&1 | 2 | 3becomes&(1 | 2 | 3), andbox 1 | 2 | 3becomesbox (1 | 2 | 3). Without parens, the or-pattern binds incorrectly — only the first alternative gets the@/&/box, causing E0408.