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
This commit is contained in:
@@ -95,11 +95,9 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<
|
||||
cx.expr_call_global(span, cmp_path.clone(), args)
|
||||
};
|
||||
|
||||
let eq_arm = cx.arm(span,
|
||||
vec![cx.pat_path(span, equals_path.clone())],
|
||||
old);
|
||||
let eq_arm = cx.arm(span, cx.pat_path(span, equals_path.clone()), old);
|
||||
let neq_arm = cx.arm(span,
|
||||
vec![cx.pat_ident(span, test_id)],
|
||||
cx.pat_ident(span, test_id),
|
||||
cx.expr_ident(span, test_id));
|
||||
|
||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
||||
|
||||
@@ -160,10 +160,10 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
|
||||
};
|
||||
|
||||
let eq_arm = cx.arm(span,
|
||||
vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))],
|
||||
cx.pat_some(span, cx.pat_path(span, ordering.clone())),
|
||||
old);
|
||||
let neq_arm = cx.arm(span,
|
||||
vec![cx.pat_ident(span, test_id)],
|
||||
cx.pat_ident(span, test_id),
|
||||
cx.expr_ident(span, test_id));
|
||||
|
||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
||||
|
||||
@@ -119,9 +119,7 @@ fn decodable_substructure(cx: &mut ExtCtxt<'_>,
|
||||
vec![idx, exprdecode.clone()]))
|
||||
});
|
||||
|
||||
arms.push(cx.arm(v_span,
|
||||
vec![cx.pat_lit(v_span, cx.expr_usize(v_span, i))],
|
||||
decoded));
|
||||
arms.push(cx.arm(v_span, cx.pat_lit(v_span, cx.expr_usize(v_span, i)), decoded));
|
||||
}
|
||||
|
||||
arms.push(cx.arm_unreachable(trait_span));
|
||||
|
||||
@@ -1071,7 +1071,7 @@ impl<'a> MethodDef<'a> {
|
||||
for (arg_expr, pat) in self_args.iter().zip(patterns) {
|
||||
body = cx.expr_match(trait_.span,
|
||||
arg_expr.clone(),
|
||||
vec![cx.arm(trait_.span, vec![pat.clone()], body)])
|
||||
vec![cx.arm(trait_.span, pat.clone(), body)])
|
||||
}
|
||||
|
||||
body
|
||||
@@ -1311,7 +1311,7 @@ impl<'a> MethodDef<'a> {
|
||||
nonself_args,
|
||||
&substructure);
|
||||
|
||||
cx.arm(sp, vec![single_pat], arm_expr)
|
||||
cx.arm(sp, single_pat, arm_expr)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1337,7 +1337,7 @@ impl<'a> MethodDef<'a> {
|
||||
_ => None,
|
||||
};
|
||||
if let Some(arm) = default {
|
||||
match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm));
|
||||
match_arms.push(cx.arm(sp, cx.pat_wild(sp), arm));
|
||||
}
|
||||
|
||||
// We will usually need the catch-all after matching the
|
||||
|
||||
@@ -716,7 +716,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||
// But the nested match expression is proved to perform not as well
|
||||
// as series of let's; the first approach does.
|
||||
let pat = self.ecx.pat_tuple(self.fmtsp, pats);
|
||||
let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array);
|
||||
let arm = self.ecx.arm(self.fmtsp, pat, args_array);
|
||||
let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
|
||||
let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user