Skip to content

Commit 1870537

Browse files
committed
initial implementation of or-pattern parsing
Initial implementation of parsing or-patterns e.g., `Some(Foo | Bar)`. This is a partial implementation of RFC 2535.
1 parent 1713ac4 commit 1870537

File tree

22 files changed

+142
-60
lines changed

22 files changed

+142
-60
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# `or_patterns`
2+
3+
The tracking issue for this feature is: [#54883]
4+
5+
[#54883]: https://github.com/rust-lang/rust/issues/54883
6+
7+
------------------------
8+
9+
The `or_pattern` language feature allows `|` to be arbitrarily nested within
10+
a pattern, for example, `Some(A(0) | B(1 | 2))` becomes a valid pattern.
11+
12+
## Examples
13+
14+
```rust,ignore
15+
#![feature(or_patterns)]
16+
17+
pub enum Foo {
18+
Bar,
19+
Baz,
20+
Quux,
21+
}
22+
23+
pub fn example(maybe_foo: Option<Foo>) {
24+
match maybe_foo {
25+
Some(Foo::Bar | Foo::Baz) => {
26+
println!("The value contained `Bar` or `Baz`");
27+
}
28+
Some(_) => {
29+
println!("The value did not contain `Bar` or `Baz`");
30+
}
31+
None => {
32+
println!("The value was `None`");
33+
}
34+
}
35+
}
36+
```

src/librustc/hir/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,8 @@ pub enum PatKind {
978978
TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>),
979979

980980
/// An or-pattern `A | B | C`.
981-
Or(Vec<P<Pat>>),
981+
/// Invariant: `pats.len() >= 2`.
982+
Or(HirVec<P<Pat>>),
982983

983984
/// A path pattern for an unit struct/variant or a (maybe-associated) constant.
984985
Path(QPath),

src/librustc/hir/print.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use syntax::source_map::{SourceMap, Spanned};
44
use syntax::parse::ParseSess;
55
use syntax::print::pp::{self, Breaks};
66
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
7-
use syntax::print::pprust::{self, Comments, PrintState, SeparatorSpacing};
7+
use syntax::print::pprust::{self, Comments, PrintState};
88
use syntax::symbol::kw;
99
use syntax::util::parser::{self, AssocOp, Fixity};
1010
use syntax_pos::{self, BytePos, FileName};
@@ -1688,8 +1688,7 @@ impl<'a> State<'a> {
16881688
self.s.word("}");
16891689
}
16901690
PatKind::Or(ref pats) => {
1691-
let spacing = SeparatorSpacing::Both;
1692-
self.strsep("|", spacing, Inconsistent, &pats[..], |s, p| s.print_pat(&p))?;
1691+
self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p));
16931692
}
16941693
PatKind::Tuple(ref elts, ddpos) => {
16951694
self.popen();

src/librustc_mir/build/matches/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,9 +658,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
658658
}
659659
}
660660
PatternKind::Or { ref pats } => {
661-
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
662661
for pat in pats {
663-
self.visit_bindings(&pat, &pattern_user_ty.clone(), f);
662+
self.visit_bindings(&pat, pattern_user_ty.clone(), f);
664663
}
665664
}
666665
}

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
/// D((r_1, p_(i,2), .., p_(i,n)))
7676
/// D((r_2, p_(i,2), .., p_(i,n)))
7777
///
78+
/// Note that the OR-patterns are not always used directly in Rust, but are used to derive
79+
/// the exhaustive integer matching rules, so they're written here for posterity.
80+
///
7881
/// The algorithm for computing `U`
7982
/// -------------------------------
8083
/// The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).

src/librustc_mir/hair/pattern/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ pub enum PatternKind<'tcx> {
176176
suffix: Vec<Pattern<'tcx>>,
177177
},
178178

179-
/// or-pattern
179+
/// An or-pattern, e.g. `p | q`.
180+
/// Invariant: `pats.len() >= 2`.
180181
Or {
181182
pats: Vec<Pattern<'tcx>>,
182183
},

src/librustc_typeck/check/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
313313
PatKind::Or(ref pats) => {
314314
let expected_ty = self.structurally_resolved_type(pat.span, expected);
315315
for pat in pats {
316-
self.check_pat_walk(pat, expected, def_bm, false);
316+
self.check_pat_walk(pat, expected, def_bm, discrim_span);
317317
}
318318
expected_ty
319319
}

src/libsyntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ pub enum PatKind {
650650
TupleStruct(Path, Vec<P<Pat>>),
651651

652652
/// An or-pattern `A | B | C`.
653+
/// Invariant: `pats.len() >= 2`.
653654
Or(Vec<P<Pat>>),
654655

655656
/// A possibly qualified path pattern.

src/libsyntax/feature_gate.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@ declare_features! (
559559
// Allows `impl Trait` to be used inside type aliases (RFC 2515).
560560
(active, type_alias_impl_trait, "1.38.0", Some(63063), None),
561561

562+
// Allows the use of or-patterns, e.g. `0 | 1`.
563+
(active, or_patterns, "1.38.0", Some(54883), None),
564+
562565
// -------------------------------------------------------------------------
563566
// feature-group-end: actual feature gates
564567
// -------------------------------------------------------------------------
@@ -571,6 +574,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
571574
sym::impl_trait_in_bindings,
572575
sym::generic_associated_types,
573576
sym::const_generics,
577+
sym::or_patterns,
574578
sym::let_chains,
575579
];
576580

@@ -2443,6 +2447,7 @@ pub fn check_crate(krate: &ast::Crate,
24432447
gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental");
24442448
gate_all!(async_closure_spans, async_closure, "async closures are unstable");
24452449
gate_all!(yield_spans, generators, "yield syntax is experimental");
2450+
gate_all!(or_pattern_spans, or_patterns, "or-patterns syntax is experimental");
24462451

24472452
let visitor = &mut PostExpansionVisitor {
24482453
context: &ctx,

src/libsyntax/parse/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ pub struct ParseSess {
6666
// Places where `yield e?` exprs were used and should be feature gated.
6767
pub yield_spans: Lock<Vec<Span>>,
6868
pub injected_crate_name: Once<Symbol>,
69+
// Places where or-patterns e.g. `Some(Foo | Bar)` were used and should be feature gated.
70+
pub or_pattern_spans: Lock<Vec<Span>>,
6971
}
7072

7173
impl ParseSess {
@@ -96,6 +98,7 @@ impl ParseSess {
9698
async_closure_spans: Lock::new(Vec::new()),
9799
yield_spans: Lock::new(Vec::new()),
98100
injected_crate_name: Once::new(),
101+
or_pattern_spans: Lock::new(Vec::new()),
99102
}
100103
}
101104

0 commit comments

Comments
 (0)