diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-09-06 09:36:39 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-06 09:36:39 +0200 |
| commit | 3c1630aa386582644759514f74b2b0a7601fb379 (patch) | |
| tree | d37aefb8ec1e33b0f1292f1743cb623ca37e17e9 /src/libsyntax/parse | |
| parent | ab75a1713a00e6d61a2bdf4ddc3d36713f03ce19 (diff) | |
| parent | 16ba5029a19eaa5968e61f4447a2d3ebf3367dc2 (diff) | |
| download | rust-3c1630aa386582644759514f74b2b0a7601fb379.tar.gz rust-3c1630aa386582644759514f74b2b0a7601fb379.zip | |
Rollup merge of #64111 - Centril:ast-only-patkind-or, r=petrochenkov
or-patterns: Uniformly use `PatKind::Or` in AST & Fix/Cleanup resolve
Following up on work in https://github.com/rust-lang/rust/pull/63693 and https://github.com/rust-lang/rust/pull/61708, in this PR we:
- Uniformly use `PatKind::Or(...)` in AST:
- Change `ast::Arm.pats: Vec<P<Pat>>` => `ast::Arm.pat: P<Pat>`
- Change `ast::ExprKind::Let.0: Vec<P<Pat>>` => `ast::ExprKind::Let.0: P<Pat>`
- Adjust `librustc_resolve/late.rs` to correctly handle or-patterns at any level of nesting as a result.
In particular, the already-bound check which rejects e.g. `let (a, a);` now accounts for or-patterns. The consistency checking (ensures no missing bindings and binding mode consistency) also now accounts for or-patterns. In the process, a bug was found in the current compiler which allowed:
```rust
enum E<T> { A(T, T), B(T) }
use E::*;
fn foo() {
match A(0, 1) {
B(mut a) | A(mut a, mut a) => {}
}
}
```
The new algorithms took a few iterations to get right. I tried several clever schemes but ultimately a version based on a stack of hashsets and recording product/sum contexts was chosen since it is more clearly correct.
- Clean up `librustc_resolve/late.rs` by, among other things, using a new `with_rib` function to better ensure stack dicipline.
- Do not push the change in AST to HIR for now to avoid doing too much in this PR. To cope with this, we introduce a temporary hack in `rustc::hir::lowering` (clearly marked in the diff).
cc https://github.com/rust-lang/rust/issues/54883
cc @dlrobertson @matthewjasper
r? @petrochenkov
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser/expr.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/pat.rs | 10 |
2 files changed, 3 insertions, 15 deletions
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index e502a08f4b2..3db9c899dba 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1250,8 +1250,7 @@ impl<'a> Parser<'a> { /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { let lo = self.prev_span; - // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead. - let pat = self.parse_top_pat_unpack(GateOr::No)?; + let pat = self.parse_top_pat(GateOr::No)?; self.expect(&token::Eq)?; let expr = self.with_res( Restrictions::NO_STRUCT_LITERAL, @@ -1393,8 +1392,7 @@ impl<'a> Parser<'a> { crate fn parse_arm(&mut self) -> PResult<'a, Arm> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; - // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead. - let pat = self.parse_top_pat_unpack(GateOr::No)?; + let pat = self.parse_top_pat(GateOr::No)?; let guard = if self.eat_keyword(kw::If) { Some(self.parse_expr()?) } else { @@ -1455,7 +1453,7 @@ impl<'a> Parser<'a> { Ok(ast::Arm { attrs, - pats: pat, // FIXME(or_patterns, Centril | dlrobertson): this should just be `pat,`. + pat, guard, body: expr, span: lo.to(hi), diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 823f880337d..669f657160b 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -36,16 +36,6 @@ impl<'a> Parser<'a> { self.parse_pat_with_range_pat(true, expected) } - // FIXME(or_patterns, Centril | dlrobertson): - // remove this and use `parse_top_pat` everywhere it is used instead. - pub(super) fn parse_top_pat_unpack(&mut self, gate_or: GateOr) -> PResult<'a, Vec<P<Pat>>> { - self.parse_top_pat(gate_or) - .map(|pat| pat.and_then(|pat| match pat.node { - PatKind::Or(pats) => pats, - node => vec![self.mk_pat(pat.span, node)], - })) - } - /// Entry point to the main pattern parser. /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level. pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P<Pat>> { |
