Skip to content

Commit a4cd03d

Browse files
committed
Auto merge of #66296 - Centril:bindings_after_at-init, r=pnkfelix
Initial implementation of `#![feature(bindings_after_at)]` Following up on #16053, under the gate `#![feature(bindings_after_at)]`, `x @ Some(y)` is allowed subject to restrictions necessary for soundness. The implementation and test suite should be fairly complete now. One aspect that is not covered is the interaction with nested `#![feature(or_patterns)]`. This is not possible to test at the moment in a good way because that feature has not progressed sufficiently and has fatal errors in MIR building. We should make sure to add such tests before we stabilize both features (but shipping one of them is fine). r? @pnkfelix cc @nikomatsakis @matthewjasper @pcwalton cc #65490
2 parents 9ae6ced + acfe582 commit a4cd03d

File tree

53 files changed

+2412
-187
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2412
-187
lines changed

Diff for: src/librustc/hir/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,16 @@ impl Pat {
921921
pub fn walk(&self, mut it: impl FnMut(&Pat) -> bool) {
922922
self.walk_(&mut it)
923923
}
924+
925+
/// Walk the pattern in left-to-right order.
926+
///
927+
/// If you always want to recurse, prefer this method over `walk`.
928+
pub fn walk_always(&self, mut it: impl FnMut(&Pat)) {
929+
self.walk(|p| {
930+
it(p);
931+
true
932+
})
933+
}
924934
}
925935

926936
/// A single field in a struct pattern.

Diff for: src/librustc/hir/pat_util.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,10 @@ impl hir::Pat {
7979
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
8080
/// `match foo() { Some(a) => (), None => () }`
8181
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident)) {
82-
self.walk(|p| {
82+
self.walk_always(|p| {
8383
if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
8484
f(binding_mode, p.hir_id, p.span, ident);
8585
}
86-
true
8786
});
8887
}
8988

Diff for: src/librustc/ty/context.rs

+7
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,13 @@ impl<'tcx> TypeckTables<'tcx> {
648648
}
649649
}
650650

651+
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
652+
self.pat_binding_modes().get(id).copied().or_else(|| {
653+
s.delay_span_bug(sp, "missing binding mode");
654+
None
655+
})
656+
}
657+
651658
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
652659
LocalTableInContext {
653660
local_id_root: self.local_id_root,

Diff for: src/librustc_error_codes/error_codes/E0303.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
3+
Sub-bindings, e.g. `ref x @ Some(ref y)` are now allowed under
4+
`#![feature(bindings_after_at)]` and checked to make sure that
5+
memory safety is upheld.
6+
7+
--------------
8+
19
In certain cases it is possible for sub-bindings to violate memory safety.
210
Updates to the borrow checker in a future version of Rust may remove this
311
restriction, but for now patterns must be rewritten without sub-bindings.
412

513
Before:
614

7-
```compile_fail,E0303
15+
```compile_fail
816
match Some("hi".to_string()) {
917
ref op_string_ref @ Some(s) => {},
1018
None => {},

Diff for: src/librustc_feature/active.rs

+4
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ declare_features! (
539539
/// Allows the use of `loop` and `while` in constants.
540540
(active, const_loop, "1.41.0", Some(52000), None),
541541

542+
/// Allows bindings in the subpattern of a binding pattern.
543+
/// For example, you can write `x @ Some(y)`.
544+
(active, bindings_after_at, "1.41.0", Some(65490), None),
545+
542546
// -------------------------------------------------------------------------
543547
// feature-group-end: actual feature gates
544548
// -------------------------------------------------------------------------

Diff for: src/librustc_mir/build/mod.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -816,15 +816,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
816816
if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) {
817817
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
818818
name = ident.name;
819-
820-
if let Some(&bm) = hir_tables.pat_binding_modes().get(pat.hir_id) {
821-
if bm == ty::BindByValue(hir::Mutability::Mut) {
819+
match hir_tables.extract_binding_mode(tcx.sess, pat.hir_id, pat.span) {
820+
Some(ty::BindByValue(hir::Mutability::Mut)) => {
822821
mutability = Mutability::Mut;
823-
} else {
824-
mutability = Mutability::Not;
825822
}
826-
} else {
827-
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
823+
Some(_) => mutability = Mutability::Not,
824+
_ => {}
828825
}
829826
}
830827
}

0 commit comments

Comments
 (0)