diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 690cff483b07c..a2cc585fc51fd 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,7 +87,7 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(boostrap_stdarch_ignore_this, feature(bind_by_move_pattern_guards))] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 94323b15b696f..f949b529e9762 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -1345,13 +1345,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// any, and then branches to the arm. Returns the block for the case where /// the guard fails. /// - /// Note: we check earlier that if there is a guard, there cannot be move - /// bindings (unless feature(bind_by_move_pattern_guards) is used). This - /// isn't really important for the self-consistency of this fn, but the - /// reason for it should be clear: after we've done the assignments, if - /// there were move bindings, further tests would be a use-after-move. - /// bind_by_move_pattern_guards avoids this by only moving the binding once - /// the guard has evaluated to true (see below). + /// Note: we do not check earlier that if there is a guard, + /// there cannot be move bindings. We avoid a use-after-move by only + /// moving the binding once the guard has evaluated to true (see below). fn bind_and_guard_matched_candidate<'pat>( &mut self, candidate: Candidate<'pat, 'tcx>, diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index d80449ac23724..908dd601df3d0 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -157,81 +157,6 @@ match x { See also the error E0303. "##, -E0008: r##" -Names bound in match arms retain their type in pattern guards. As such, if a -name is bound by move in a pattern, it should also be moved to wherever it is -referenced in the pattern guard code. Doing so however would prevent the name -from being available in the body of the match arm. Consider the following: - -```compile_fail,E0008 -match Some("hi".to_string()) { - Some(s) if s.len() == 0 => {}, // use s. - _ => {}, -} -``` - -The variable `s` has type `String`, and its use in the guard is as a variable of -type `String`. The guard code effectively executes in a separate scope to the -body of the arm, so the value would be moved into this anonymous scope and -therefore becomes unavailable in the body of the arm. - -The problem above can be solved by using the `ref` keyword. - -``` -match Some("hi".to_string()) { - Some(ref s) if s.len() == 0 => {}, - _ => {}, -} -``` - -Though this example seems innocuous and easy to solve, the problem becomes clear -when it encounters functions which consume the value: - -```compile_fail,E0008 -struct A{} - -impl A { - fn consume(self) -> usize { - 0 - } -} - -fn main() { - let a = Some(A{}); - match a { - Some(y) if y.consume() > 0 => {} - _ => {} - } -} -``` - -In this situation, even the `ref` keyword cannot solve it, since borrowed -content cannot be moved. This problem cannot be solved generally. If the value -can be cloned, here is a not-so-specific solution: - -``` -#[derive(Clone)] -struct A{} - -impl A { - fn consume(self) -> usize { - 0 - } -} - -fn main() { - let a = Some(A{}); - match a{ - Some(ref y) if y.clone().consume() > 0 => {} - _ => {} - } -} -``` - -If the value will be consumed in the pattern guard, using its clone will not -move its ownership, so the code works. -"##, - E0009: r##" In a pattern, all values that don't implement the `Copy` trait have to be bound the same way. The goal here is to avoid binding simultaneously by-move and @@ -475,13 +400,15 @@ for item in xs { "##, E0301: r##" +#### Note: this error code is no longer emitted by the compiler. + Mutable borrows are not allowed in pattern guards, because matching cannot have side effects. Side effects could alter the matched object or the environment on which the match depends in such a way, that the match would not be exhaustive. For instance, the following would not match any arm if mutable borrows were allowed: -```compile_fail,E0301 +```compile_fail,E0596 match Some(()) { None => { }, option if option.take().is_none() => { @@ -493,13 +420,15 @@ match Some(()) { "##, E0302: r##" +#### Note: this error code is no longer emitted by the compiler. + Assignments are not allowed in pattern guards, because matching cannot have side effects. Side effects could alter the matched object or the environment on which the match depends in such a way, that the match would not be exhaustive. For instance, the following would not match any arm if assignments were allowed: -```compile_fail,E0302 +```compile_fail,E0594 match Some(()) { None => { }, option if { option = None; false } => { }, @@ -1989,7 +1918,6 @@ When matching on a variable it cannot be mutated in the match guards, as this could cause the match to be non-exhaustive: ```compile_fail,E0510 -#![feature(bind_by_move_pattern_guards)] let mut x = Some(0); match x { None => (), @@ -2451,6 +2379,7 @@ There are some known bugs that trigger this message. ; +// E0008, // cannot bind by-move into a pattern guard // E0298, // cannot compare constants // E0299, // mismatched types between arms // E0471, // constant evaluation error (in pattern) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 5352888006c30..1b4b56082a696 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -5,11 +5,6 @@ use super::_match::WitnessPreference::*; use super::{Pattern, PatternContext, PatternError, PatternKind}; use rustc::middle::borrowck::SignalledError; -use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; -use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; -use rustc::middle::expr_use_visitor as euv; -use rustc::middle::mem_categorization::cmt_; -use rustc::middle::region; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; @@ -36,9 +31,7 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) -> SignalledError { let mut visitor = MatchVisitor { tcx, - body_owner: def_id, tables: tcx.body_tables(body_id), - region_scope_tree: &tcx.region_scope_tree(def_id), param_env: tcx.param_env(def_id), identity_substs: InternalSubsts::identity_for_item(tcx, def_id), signalled_error: SignalledError::NoErrorsSeen, @@ -53,11 +46,9 @@ fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBu struct MatchVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body_owner: DefId, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, identity_substs: SubstsRef<'tcx>, - region_scope_tree: &'a region::ScopeTree, signalled_error: SignalledError, } @@ -151,11 +142,8 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. - if let Some(ref guard) = arm.guard { + if arm.guard.is_some() { self.signalled_error = SignalledError::SawSomeError; - if !self.tcx.features().bind_by_move_pattern_guards { - check_for_mutation_in_guard(self, &guard); - } } // Third, perform some lints. @@ -582,19 +570,10 @@ fn check_legality_of_move_bindings( "cannot bind by-move with sub-bindings") .span_label(p.span, "binds an already bound by-move value by moving it") .emit(); - } else if has_guard { - if !cx.tcx.features().bind_by_move_pattern_guards { - let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008, - "cannot bind by-move into a pattern guard"); - err.span_label(p.span, "moves value into pattern guard"); - if cx.tcx.sess.opts.unstable_features.is_nightly_build() { - err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \ - crate attributes to enable"); - } - err.emit(); + } else if !has_guard { + if let Some(_by_ref_span) = by_ref_span { + span_vec.push(p.span); } - } else if let Some(_by_ref_span) = by_ref_span { - span_vec.push(p.span); } }; @@ -636,67 +615,6 @@ fn check_legality_of_move_bindings( } } -/// Ensures that a pattern guard doesn't borrow by mutable reference or assign. -// -// FIXME: this should be done by borrowck. -fn check_for_mutation_in_guard(cx: &MatchVisitor<'_, '_>, guard: &hir::Guard) { - let mut checker = MutationChecker { - cx, - }; - match guard { - hir::Guard::If(expr) => - ExprUseVisitor::new(&mut checker, - cx.tcx, - cx.body_owner, - cx.param_env, - cx.region_scope_tree, - cx.tables, - None).walk_expr(expr), - }; -} - -struct MutationChecker<'a, 'tcx> { - cx: &'a MatchVisitor<'a, 'tcx>, -} - -impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { - fn matched_pat(&mut self, _: &Pat, _: &cmt_<'_>, _: euv::MatchMode) {} - fn consume(&mut self, _: hir::HirId, _: Span, _: &cmt_<'_>, _: ConsumeMode) {} - fn consume_pat(&mut self, _: &Pat, _: &cmt_<'_>, _: ConsumeMode) {} - fn borrow(&mut self, - _: hir::HirId, - span: Span, - _: &cmt_<'_>, - _: ty::Region<'tcx>, - kind:ty:: BorrowKind, - _: LoanCause) { - match kind { - ty::MutBorrow => { - let mut err = struct_span_err!(self.cx.tcx.sess, span, E0301, - "cannot mutably borrow in a pattern guard"); - err.span_label(span, "borrowed mutably in pattern guard"); - if self.cx.tcx.sess.opts.unstable_features.is_nightly_build() { - err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \ - crate attributes to enable"); - } - err.emit(); - } - ty::ImmBorrow | ty::UniqueImmBorrow => {} - } - } - fn decl_without_init(&mut self, _: hir::HirId, _: Span) {} - fn mutate(&mut self, _: hir::HirId, span: Span, _: &cmt_<'_>, mode: MutateMode) { - match mode { - MutateMode::JustWrite | MutateMode::WriteAndRead => { - struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard") - .span_label(span, "assignment in pattern guard") - .emit(); - } - MutateMode::Init => {} - } - } -} - /// Forbids bindings in `@` patterns. This is necessary for memory safety, /// because of the way rvalues are handled in the borrow check. (See issue /// #14587.) diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index cf2da4ffa2af0..a5a8315a1e73f 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,7 +8,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![recursion_limit="256"] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 301946733dc55..25ee8b4273d52 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/")] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(rustc_private)] #![feature(arbitrary_self_types)] #![feature(box_patterns)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 71050b0dcd1f5..8a7b66f019669 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -238,7 +238,7 @@ #![feature(array_error_internals)] #![feature(asm)] #![feature(associated_type_bounds)] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_target_has_atomic)] diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs index 6c0b271c6c5e9..eff9f90a8619e 100644 --- a/src/libsyntax/feature_gate/accepted.rs +++ b/src/libsyntax/feature_gate/accepted.rs @@ -241,6 +241,8 @@ declare_features! ( (accepted, underscore_const_names, "1.37.0", Some(54912), None), /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. (accepted, async_await, "1.39.0", Some(50547), None), + /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. + (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 5a248df6af252..dd78777b56986 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -461,9 +461,6 @@ declare_features! ( /// Allows non-builtin attributes in inner attribute position. (active, custom_inner_attributes, "1.30.0", Some(54726), None), - /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. - (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - /// Allows `impl Trait` in bindings (`let`, `const`, `static`). (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 49efbce482fa3..aaf6f3e537eb6 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -7,7 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![feature(bind_by_move_pattern_guards)] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(const_fn)] #![feature(const_transmute)] diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs index 18e0642eb3427..c898d3a6f168c 100644 --- a/src/test/mir-opt/match-arm-scopes.rs +++ b/src/test/mir-opt/match-arm-scopes.rs @@ -8,8 +8,6 @@ // all of the bindings for that scope. // * No drop flags are used. -#![feature(nll, bind_by_move_pattern_guards)] - fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 { match items { (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1, diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs deleted file mode 100644 index bc9b3a8de4ef5..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::sync::mpsc::channel; - -fn main() { - let (tx, rx) = channel(); - let x = Some(rx); - tx.send(false); - match x { - Some(z) if z.recv().unwrap() => { panic!() }, - //~^ ERROR cannot bind by-move into a pattern guard - Some(z) => { assert!(!z.recv().unwrap()); }, - None => panic!() - } -} diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr deleted file mode 100644 index c5f0256c2c92f..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/bind-by-move-no-guards.rs:8:14 - | -LL | Some(z) if z.recv().unwrap() => { panic!() }, - | ^ moves value into pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs index 5b6aa7a979be5..9cbceeb945ccc 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs @@ -8,12 +8,9 @@ fn foo() -> isize { let mut x = Enum::A(&mut n); match x { Enum::A(_) if { x = Enum::B(false); false } => 1, - //~^ ERROR cannot assign in a pattern guard - //~| ERROR cannot assign `x` in match guard + //~^ ERROR cannot assign `x` in match guard Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - //~^ ERROR cannot mutably borrow in a pattern guard - //~| ERROR cannot assign in a pattern guard - //~| ERROR cannot mutably borrow `x` in match guard + //~^ ERROR cannot mutably borrow `x` in match guard Enum::A(p) => *p, Enum::B(_) => 2, } diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr index 674f137dbb043..6d05e97252d92 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -1,23 +1,3 @@ -error[E0302]: cannot assign in a pattern guard - --> $DIR/borrowck-mutate-in-guard.rs:10:25 - | -LL | Enum::A(_) if { x = Enum::B(false); false } => 1, - | ^^^^^^^^^^^^^^^^^^ assignment in pattern guard - -error[E0301]: cannot mutably borrow in a pattern guard - --> $DIR/borrowck-mutate-in-guard.rs:13:38 - | -LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - | ^ borrowed mutably in pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error[E0302]: cannot assign in a pattern guard - --> $DIR/borrowck-mutate-in-guard.rs:13:41 - | -LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - | ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard - error[E0510]: cannot assign `x` in match guard --> $DIR/borrowck-mutate-in-guard.rs:10:25 | @@ -27,7 +7,7 @@ LL | Enum::A(_) if { x = Enum::B(false); false } => 1, | ^^^^^^^^^^^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:13:33 + --> $DIR/borrowck-mutate-in-guard.rs:12:33 | LL | match x { | - value is immutable in match guard @@ -35,7 +15,6 @@ LL | match x { LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, | ^^^^^^ cannot mutably borrow -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0301, E0302, E0510. -For more information about an error, try `rustc --explain E0301`. +For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/error-codes/E0008.rs b/src/test/ui/error-codes/E0008.rs deleted file mode 100644 index c87ef4cb8541f..0000000000000 --- a/src/test/ui/error-codes/E0008.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - match Some("hi".to_string()) { - Some(s) if s.len() == 0 => {}, - //~^ ERROR E0008 - _ => {}, - } -} diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr deleted file mode 100644 index 6b45439c4b587..0000000000000 --- a/src/test/ui/error-codes/E0008.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/E0008.rs:3:14 - | -LL | Some(s) if s.len() == 0 => {}, - | ^ moves value into pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/error-codes/E0301.rs b/src/test/ui/error-codes/E0301.rs deleted file mode 100644 index 3b451801c99df..0000000000000 --- a/src/test/ui/error-codes/E0301.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - match Some(()) { - None => { }, - option if option.take().is_none() => {}, //~ ERROR E0301 - Some(_) => { } //~^ ERROR E0596 - } -} diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr deleted file mode 100644 index 4f12fd3850e33..0000000000000 --- a/src/test/ui/error-codes/E0301.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0301]: cannot mutably borrow in a pattern guard - --> $DIR/E0301.rs:4:19 - | -LL | option if option.take().is_none() => {}, - | ^^^^^^ borrowed mutably in pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error[E0596]: cannot borrow `option` as mutable, as it is immutable for the pattern guard - --> $DIR/E0301.rs:4:19 - | -LL | option if option.take().is_none() => {}, - | ^^^^^^ cannot borrow as mutable - | - = note: variables bound in patterns are immutable until the end of the pattern guard - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0301, E0596. -For more information about an error, try `rustc --explain E0301`. diff --git a/src/test/ui/error-codes/E0302.rs b/src/test/ui/error-codes/E0302.rs deleted file mode 100644 index 69f5953deb223..0000000000000 --- a/src/test/ui/error-codes/E0302.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - match Some(()) { - None => { }, - option if { option = None; false } => { }, //~ ERROR E0302 - //~^ ERROR cannot assign to `option`, as it is immutable for the pattern guard - Some(_) => { } - } -} diff --git a/src/test/ui/error-codes/E0302.stderr b/src/test/ui/error-codes/E0302.stderr deleted file mode 100644 index a077fcaea4101..0000000000000 --- a/src/test/ui/error-codes/E0302.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0302]: cannot assign in a pattern guard - --> $DIR/E0302.rs:4:21 - | -LL | option if { option = None; false } => { }, - | ^^^^^^^^^^^^^ assignment in pattern guard - -error[E0594]: cannot assign to `option`, as it is immutable for the pattern guard - --> $DIR/E0302.rs:4:21 - | -LL | option if { option = None; false } => { }, - | ^^^^^^^^^^^^^ cannot assign - | - = note: variables bound in patterns are immutable until the end of the pattern guard - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0302`. diff --git a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs index 48362d0bb6282..7253d35ed2d4f 100644 --- a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs +++ b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs @@ -5,8 +5,6 @@ // See further discussion on rust-lang/rust#24535, // rust-lang/rfcs#1006, and rust-lang/rfcs#107 -#![feature(bind_by_move_pattern_guards)] - fn main() { rust_issue_24535(); rfcs_issue_1006_1(); diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs index 1ffb7f6fd4acd..82d8b9e9ed977 100644 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs +++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs @@ -5,8 +5,6 @@ // reject it. But I want to make sure that we continue to reject it // (under NLL) even when that conservaive check goes away. -#![feature(bind_by_move_pattern_guards)] - fn main() { let mut b = &mut true; match b { diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr index a8eb78b7cc007..f0264b56ea569 100644 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr +++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard - --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25 + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 | LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | ^^ - mutable borrow occurs due to use of `r` in closure diff --git a/src/test/ui/match/match-ref-mut-stability.rs b/src/test/ui/match/match-ref-mut-stability.rs index 49e0dfaa3eb84..52120360be71e 100644 --- a/src/test/ui/match/match-ref-mut-stability.rs +++ b/src/test/ui/match/match-ref-mut-stability.rs @@ -3,8 +3,6 @@ // run-pass -#![feature(bind_by_move_pattern_guards)] - // Test that z always point to the same temporary. fn referent_stability() { let p; diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index 5fc9966cdf807..2e6d675fb641e 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -1,8 +1,6 @@ // Test that we have enough false edges to avoid exposing the exact matching // algorithm in borrow checking. -#![feature(bind_by_move_pattern_guards)] - fn guard_always_precedes_arm(y: i32) { let mut x; // x should always be initialized, as the only way to reach the arm is diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index 3d9037bbe7bf8..06fe564ac69e3 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -1,11 +1,11 @@ error[E0381]: use of possibly-uninitialized variable: `x` - --> $DIR/match-cfg-fake-edges.rs:23:13 + --> $DIR/match-cfg-fake-edges.rs:21:13 | LL | x; | ^ use of possibly-uninitialized `x` error[E0382]: use of moved value: `x` - --> $DIR/match-cfg-fake-edges.rs:37:13 + --> $DIR/match-cfg-fake-edges.rs:35:13 | LL | let x = String::new(); | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs index 601c46ff86cc7..81ae19ebf8a72 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.rs +++ b/src/test/ui/nll/match-guards-partially-borrow.rs @@ -5,8 +5,6 @@ // Test that we don't allow mutating the value being matched on in a way that // changes which patterns it matches, until we have chosen an arm. -#![feature(bind_by_move_pattern_guards)] - fn ok_mutation_in_guard(mut q: i32) { match q { // OK, mutation doesn't change which patterns g matches diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr index b2951fd339da4..48e3a7c699318 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.stderr +++ b/src/test/ui/nll/match-guards-partially-borrow.stderr @@ -1,5 +1,5 @@ error[E0510]: cannot assign `q` in match guard - --> $DIR/match-guards-partially-borrow.rs:57:13 + --> $DIR/match-guards-partially-borrow.rs:55:13 | LL | match q { | - value is immutable in match guard @@ -8,7 +8,7 @@ LL | q = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `r` in match guard - --> $DIR/match-guards-partially-borrow.rs:69:13 + --> $DIR/match-guards-partially-borrow.rs:67:13 | LL | match r { | - value is immutable in match guard @@ -17,7 +17,7 @@ LL | r = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `t` in match guard - --> $DIR/match-guards-partially-borrow.rs:93:13 + --> $DIR/match-guards-partially-borrow.rs:91:13 | LL | match t { | - value is immutable in match guard @@ -26,7 +26,7 @@ LL | t = true; | ^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x.0` in match guard - --> $DIR/match-guards-partially-borrow.rs:107:22 + --> $DIR/match-guards-partially-borrow.rs:105:22 | LL | match x { | - value is immutable in match guard @@ -35,7 +35,7 @@ LL | Some(ref mut r) => *r = None, | ^^^^^^^^^ cannot mutably borrow error[E0506]: cannot assign to `t` because it is borrowed - --> $DIR/match-guards-partially-borrow.rs:119:13 + --> $DIR/match-guards-partially-borrow.rs:117:13 | LL | s if { | - borrow of `t` occurs here @@ -46,7 +46,7 @@ LL | } => (), // What value should `s` have in the arm? | - borrow later used here error[E0510]: cannot assign `y` in match guard - --> $DIR/match-guards-partially-borrow.rs:130:13 + --> $DIR/match-guards-partially-borrow.rs:128:13 | LL | match *y { | -- value is immutable in match guard @@ -55,7 +55,7 @@ LL | y = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `z` in match guard - --> $DIR/match-guards-partially-borrow.rs:141:13 + --> $DIR/match-guards-partially-borrow.rs:139:13 | LL | match z { | - value is immutable in match guard @@ -64,7 +64,7 @@ LL | z = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `a` in match guard - --> $DIR/match-guards-partially-borrow.rs:153:13 + --> $DIR/match-guards-partially-borrow.rs:151:13 | LL | match a { | - value is immutable in match guard @@ -73,7 +73,7 @@ LL | a = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `b` in match guard - --> $DIR/match-guards-partially-borrow.rs:164:13 + --> $DIR/match-guards-partially-borrow.rs:162:13 | LL | match b { | - value is immutable in match guard diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs index 041e410df85c9..1e086160f3f34 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs @@ -4,8 +4,6 @@ // run-pass -#![feature(bind_by_move_pattern_guards)] - use std::sync::mpsc::channel; fn main() { diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr deleted file mode 100644 index fe1f699074735..0000000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:36:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr deleted file mode 100644 index fe1f699074735..0000000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:36:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr deleted file mode 100644 index 34e8b0e14399e..0000000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:41:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr deleted file mode 100644 index 34e8b0e14399e..0000000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate.rs:41:1 - | -LL | / fn main() { -LL | | foo(107) -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr deleted file mode 100644 index 7a7b1c253528f..0000000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/feature-gate.rs:28:16 - | -LL | A { a: v } if *v == 42 => v, - | ^ moves value into pattern guard - | - = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs deleted file mode 100644 index 69fce0bc775f7..0000000000000 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Check that pattern-guards with move-bound variables is only allowed -// with the appropriate set of feature gates. (Note that we require -// the code to opt into MIR-borrowck in *some* way before the feature -// will work; we use the revision system here to enumerate a number of -// ways that opt-in could occur.) - -// gate-test-bind_by_move_pattern_guards - -// revisions: no_gate gate_and_2015 gate_and_2018 - -// (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.) -// ignore-compare-mode-nll - -#![feature(rustc_attrs)] - -#![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))] -#![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))] - -//[gate_and_2015] edition:2015 -//[gate_and_2018] edition:2018 - -struct A { a: Box } - -fn foo(n: i32) { - let x = A { a: Box::new(n) }; - let _y = match x { - - A { a: v } if *v == 42 => v, - //[no_gate]~^ ERROR cannot bind by-move into a pattern guard - - _ => Box::new(0) - }; -} - -#[rustc_error] -fn main() { - foo(107) -} -//[gate_and_2015]~^^^ ERROR compilation successful -//[gate_and_2018]~^^^^ ERROR compilation successful diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs new file mode 100644 index 0000000000000..3161d6fbbe647 --- /dev/null +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs @@ -0,0 +1,11 @@ +// This test used to emit E0008 but now passed since `bind_by_move_pattern_guards` +// have been stabilized. + +// check-pass + +fn main() { + match Some("hi".to_string()) { + Some(s) if s.len() == 0 => {}, + _ => {}, + } +} diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs index eccb4e417b694..b716fc870e071 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs @@ -1,5 +1,3 @@ -#![feature(bind_by_move_pattern_guards)] - // run-pass struct A { a: Box } diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs index 602a8e15cb180..d1f685f3e7a6d 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs @@ -1,5 +1,3 @@ -#![feature(bind_by_move_pattern_guards)] - enum VecWrapper { A(Vec) } fn foo(x: VecWrapper) -> usize { diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr index c9e8fc8ee532b..7becd013249d4 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-across-arms.rs:7:36 + --> $DIR/rfc-reject-double-move-across-arms.rs:5:36 | LL | VecWrapper::A(v) if { drop(v); false } => 1, | ^ move occurs because `v` has type `std::vec::Vec`, which does not implement the `Copy` trait diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs index 77252a1ce1569..571f51c900120 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs @@ -1,5 +1,3 @@ -#![feature(bind_by_move_pattern_guards)] - struct A { a: Box } fn foo(n: i32) { diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr index a345022cee7c5..b93e72190680d 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30 + --> $DIR/rfc-reject-double-move-in-first-arm.rs:6:30 | LL | A { a: v } if { drop(v); true } => v, | ^ move occurs because `v` has type `std::boxed::Box`, which does not implement the `Copy` trait