)]}'
{
  "commit": "4521a3fb44e1663cd1b6c06ff6126283c0b87931",
  "tree": "9a83e123e0c46b29c9296248dd432ef720fc2a88",
  "parents": [
    "86390a3c03438b660c5efc64d4e18ae65982f5c0",
    "f049a64100edba2f9c91925b2dc2020ff69c7499"
  ],
  "author": {
    "name": "Jonathan Brouwer",
    "email": "jonathantbrouwer@gmail.com",
    "time": "Mon Mar 23 12:00:59 2026 +0100"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Mon Mar 23 12:00:59 2026 +0100"
  },
  "message": "Rollup merge of #154085 - aytey:fix-at-or-pattern-parens, r\u003dchenyukang\n\nParenthesize or-patterns in prefix pattern positions in pretty printer\n\nThe AST pretty printer was dropping parentheses around or-patterns when they appeared inside `@` bindings, `\u0026` references, or `box` patterns. For example:\n\n- `v @ (1 | 2 | 3)` was printed as `v @ 1 | 2 | 3`\n- `\u0026(1 | 2 | 3)` was printed as `\u00261 | 2 | 3`\n- `box (1 | 2 | 3)` was printed as `box 1 | 2 | 3`\n\nSince `|` 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.\n\nThis 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 `@`.\n\nThe fix adds a `print_pat_paren_if_or` helper that wraps `PatKind::Or` subpatterns in parentheses, and uses it in the `@`, `\u0026`, and `box` printing arms. This is similar in spirit to the existing `FixupContext` parenthesization approach used for expression printing.\n\n## Example\n\n**before** (`rustc 1.96.0-nightly (3b1b0ef4d 2026-03-11)`):\n\n```rust\n#![feature(prelude_import)]\n#![no_std]\n#![feature(box_patterns)]\nextern crate std;\n#[prelude_import]\nuse ::std::prelude::rust_2015::*;\n\n//@ pretty-compare-only\n//@ pretty-mode:expanded\n//@ pp-exact:or-pattern-paren.pp\n\nmacro_rules! or_pat { ($($name:pat),+) \u003d\u003e { $($name)|+ } }\n\nfn check_at(x: Option\u003ci32\u003e) {\n    match x {\n        Some(v @ 1 | 2 | 3) \u003d\u003e\n\n            {\n            ::std::io::_print(format_args!(\"{0}\\n\", v));\n        }\n        _ \u003d\u003e {}\n    }\n}\nfn check_ref(x: \u0026i32) { match x { \u00261 | 2 | 3 \u003d\u003e {} _ \u003d\u003e {} } }\nfn check_box(x: Box\u003ci32\u003e) { match x { box 1 | 2 | 3 \u003d\u003e {} _ \u003d\u003e {} } }\nfn main() { check_at(Some(2)); check_ref(\u00261); check_box(Box::new(1)); }\n```\n\n**after** (this branch):\n\n```rust\n#![feature(prelude_import)]\n#![no_std]\n#![feature(box_patterns)]\nextern crate std;\n#[prelude_import]\nuse ::std::prelude::rust_2015::*;\n\n//@ pretty-compare-only\n//@ pretty-mode:expanded\n//@ pp-exact:or-pattern-paren.pp\n\nmacro_rules! or_pat { ($($name:pat),+) \u003d\u003e { $($name)|+ } }\n\nfn check_at(x: Option\u003ci32\u003e) {\n    match x {\n        Some(v @ (1 | 2 | 3)) \u003d\u003e\n\n            {\n            ::std::io::_print(format_args!(\"{0}\\n\", v));\n        }\n        _ \u003d\u003e {}\n    }\n}\nfn check_ref(x: \u0026i32) { match x { \u0026(1 | 2 | 3) \u003d\u003e {} _ \u003d\u003e {} } }\nfn check_box(x: Box\u003ci32\u003e) { match x { box (1 | 2 | 3) \u003d\u003e {} _ \u003d\u003e {} } }\nfn main() { check_at(Some(2)); check_ref(\u00261); check_box(Box::new(1)); }\n```\n\nNotice `v @ 1 | 2 | 3` becomes `v @ (1 | 2 | 3)`, `\u00261 | 2 | 3` becomes `\u0026(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 `@`/`\u0026`/`box`, causing E0408.\n",
  "tree_diff": []
}
