Files
rust/tests
Jonathan Brouwer 9e25329fd6 Rollup merge of #154085 - aytey:fix-at-or-pattern-parens, r=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 (3b1b0ef4d 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.
2026-03-23 12:00:59 +01:00
..