diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 67fc3520745dd..5ab1b90642a6a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -461,7 +461,7 @@ rustc_queries! { } TypeChecking { - query check_match(key: DefId) -> () { + query check_match(key: DefId) -> SignalledError { cache_on_disk_if { key.is_local() } } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index f4b99ca368874..fb2ad2aa54d7a 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -4,7 +4,7 @@ use crate::hir::def::{DefKind, Export}; use crate::hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs}; use crate::infer::canonical::{self, Canonical}; use crate::lint; -use crate::middle::borrowck::BorrowCheckResult; +use crate::middle::borrowck::{BorrowCheckResult, SignalledError}; use crate::middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ForeignModule}; use crate::middle::cstore::{NativeLibraryKind, DepKind, CrateSource}; use crate::middle::privacy::AccessLevels; diff --git a/src/librustc_ast_borrowck/borrowck/mod.rs b/src/librustc_ast_borrowck/borrowck/mod.rs index f8ad8baa5974d..3bbd7ae5c352f 100644 --- a/src/librustc_ast_borrowck/borrowck/mod.rs +++ b/src/librustc_ast_borrowck/borrowck/mod.rs @@ -66,6 +66,13 @@ fn borrowck(tcx: TyCtxt<'_>, owner_def_id: DefId) -> &BorrowCheckResult { debug!("borrowck(body_owner_def_id={:?})", owner_def_id); + let signalled_error = tcx.check_match(owner_def_id); + if let SignalledError::SawSomeError = signalled_error { + return tcx.arena.alloc(BorrowCheckResult { + signalled_any_error: SignalledError::SawSomeError, + }) + } + let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap(); match tcx.hir().get(owner_id) { diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index a5e44a1933c9d..2afffd71fe206 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -1989,7 +1989,7 @@ 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(nll, bind_by_move_pattern_guards)] +#![feature(bind_by_move_pattern_guards)] let mut x = Some(0); match x { None => (), diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 32a8c5cd3bb28..17fd9377a1629 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -4,6 +4,7 @@ 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; @@ -26,21 +27,24 @@ use std::slice; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { +crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) -> SignalledError { let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) { tcx.hir().body_owned_by(id) } else { - return; + return SignalledError::NoErrorsSeen; }; - MatchVisitor { + 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), - }.visit_body(tcx.hir().body(body_id)); + signalled_error: SignalledError::NoErrorsSeen, + }; + visitor.visit_body(tcx.hir().body(body_id)); + visitor.signalled_error } fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> { @@ -54,6 +58,7 @@ struct MatchVisitor<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, identity_substs: SubstsRef<'tcx>, region_scope_tree: &'a region::ScopeTree, + signalled_error: SignalledError, } impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { @@ -64,11 +69,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx hir::Expr) { intravisit::walk_expr(self, ex); - match ex.node { - hir::ExprKind::Match(ref scrut, ref arms, source) => { - self.check_match(scrut, arms, source); - } - _ => {} + if let hir::ExprKind::Match(ref scrut, ref arms, source) = ex.node { + self.check_match(scrut, arms, source); } } @@ -130,7 +132,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { - fn check_patterns(&self, has_guard: bool, pats: &[P]) { + fn check_patterns(&mut self, has_guard: bool, pats: &[P]) { check_legality_of_move_bindings(self, has_guard, pats); for pat in pats { check_legality_of_bindings_in_at_patterns(self, pat); @@ -138,11 +140,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } fn check_match( - &self, + &mut self, scrut: &hir::Expr, arms: &'tcx [hir::Arm], - source: hir::MatchSource) - { + source: hir::MatchSource + ) { for arm in arms { // First, check legality of move bindings. self.check_patterns(arm.guard.is_some(), &arm.pats); @@ -150,6 +152,7 @@ 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 { + self.signalled_error = SignalledError::SawSomeError; if !self.tcx.features().bind_by_move_pattern_guards { check_for_mutation_in_guard(self, &guard); } @@ -548,7 +551,7 @@ fn maybe_point_at_variant( // Legality of move bindings checking fn check_legality_of_move_bindings( - cx: &MatchVisitor<'_, '_>, + cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pats: &[P], ) { @@ -565,7 +568,12 @@ fn check_legality_of_move_bindings( }) } let span_vec = &mut Vec::new(); - let check_move = |p: &Pat, sub: Option<&Pat>, span_vec: &mut Vec| { + let check_move = | + cx: &mut MatchVisitor<'_, '_>, + p: &Pat, + sub: Option<&Pat>, + span_vec: &mut Vec, + | { // check legality of moving out of the enum // x @ Foo(..) is legal, but x @ Foo(y) isn't. @@ -574,15 +582,17 @@ 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 && !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"); + } 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(); } - err.emit(); } else if let Some(_by_ref_span) = by_ref_span { span_vec.push(p.span); } @@ -596,7 +606,7 @@ fn check_legality_of_move_bindings( ty::BindByValue(..) => { let pat_ty = cx.tables.node_type(p.hir_id); if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { - check_move(p, sub.as_ref().map(|p| &**p), span_vec); + check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec); } } _ => {} diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr index d97883ad47a50..a33a1d00a5786 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr @@ -1,14 +1,14 @@ -warning[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/borrowck-migrate-to-nll.rs:26:18 +warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-migrate-to-nll.rs:28:21 | -LL | (|| { let bar = foo; bar.take() })(); - | ^^ --- - | | | - | | move occurs because `foo` has type `&mut std::option::Option<&i32>`, which does not implement the `Copy` trait - | | move occurs due to use in closure - | move out of `foo` occurs here +LL | let x = &mut block; + | ---------- mutable borrow occurs here +LL | let p: &'a u8 = &*block.current; + | ^^^^^^^^^^^^^^^ immutable borrow occurs here +LL | // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) +LL | drop(x); + | - mutable borrow later used here | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future = note: for more information, try `rustc --explain E0729` diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs index a64df9df25948..6dda317e57efe 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs @@ -1,4 +1,4 @@ -// This is a test of the borrowck migrate mode. It leverages #27282, a +// This is a test of the borrowck migrate mode. It leverages #38899, a // bug that is fixed by NLL: this code is (unsoundly) accepted by // AST-borrowck, but is correctly rejected by the NLL borrowck. // @@ -18,15 +18,17 @@ //[zflag] run-pass //[edition] run-pass -fn main() { - match Some(&4) { - None => {}, - ref mut foo - if { - (|| { let bar = foo; bar.take() })(); - false - } => {}, - Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."), - _ => println!("Here is some supposedly unreachable code."), - } +pub struct Block<'a> { + current: &'a u8, + unrelated: &'a u8, } + +fn bump<'a>(mut block: &mut Block<'a>) { + let x = &mut block; + let p: &'a u8 = &*block.current; + // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) + drop(x); + drop(p); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr index d97883ad47a50..a33a1d00a5786 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr @@ -1,14 +1,14 @@ -warning[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/borrowck-migrate-to-nll.rs:26:18 +warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-migrate-to-nll.rs:28:21 | -LL | (|| { let bar = foo; bar.take() })(); - | ^^ --- - | | | - | | move occurs because `foo` has type `&mut std::option::Option<&i32>`, which does not implement the `Copy` trait - | | move occurs due to use in closure - | move out of `foo` occurs here +LL | let x = &mut block; + | ---------- mutable borrow occurs here +LL | let p: &'a u8 = &*block.current; + | ^^^^^^^^^^^^^^^ immutable borrow occurs here +LL | // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes) +LL | drop(x); + | - mutable borrow later used here | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future = note: for more information, try `rustc --explain E0729` diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr deleted file mode 100644 index 43b578e9f1eaf..0000000000000 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr +++ /dev/null @@ -1,41 +0,0 @@ -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:15: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:15: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 - | -LL | match x { - | - value is immutable in match guard -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:15:33 - | -LL | match x { - | - value is immutable in match guard -... -LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, - | ^^^^^^ cannot mutably borrow - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0301, E0302, E0510. -For more information about an error, try `rustc --explain E0301`. diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs index 9ea5e5cd145a0..5b6aa7a979be5 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs @@ -9,15 +9,11 @@ fn foo() -> isize { match x { Enum::A(_) if { x = Enum::B(false); false } => 1, //~^ ERROR cannot assign in a pattern guard - //~| WARN cannot assign `x` in match guard - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~| 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 - //~| WARN cannot mutably borrow `x` in match guard - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~| 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 d39f535d8e2f7..674f137dbb043 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -5,7 +5,7 @@ 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:15:38 + --> $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 @@ -13,37 +13,29 @@ LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, = 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:15:41 + --> $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 -warning[E0510]: cannot assign `x` in match guard +error[E0510]: cannot assign `x` in match guard --> $DIR/borrowck-mutate-in-guard.rs:10:25 | LL | match x { | - value is immutable in match guard LL | Enum::A(_) if { x = Enum::B(false); false } => 1, | ^^^^^^^^^^^^^^^^^^ cannot assign - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -warning[E0510]: cannot mutably borrow `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:15:33 +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:13:33 | LL | match x { | - value is immutable in match guard ... LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, | ^^^^^^ cannot mutably borrow - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0301, E0302, E0510. For more information about an error, try `rustc --explain E0301`. diff --git a/src/test/ui/borrowck/issue-27282-mutation-in-guard.rs b/src/test/ui/borrowck/issue-27282-mutation-in-guard.rs new file mode 100644 index 0000000000000..395c7d214d0ce --- /dev/null +++ b/src/test/ui/borrowck/issue-27282-mutation-in-guard.rs @@ -0,0 +1,13 @@ +fn main() { + match Some(&4) { + None => {}, + ref mut foo + if { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard + false + } => {}, + Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."), + _ => println!("Here is some supposedly unreachable code."), + } +} diff --git a/src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr b/src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr new file mode 100644 index 0000000000000..ea7df7d5a7b61 --- /dev/null +++ b/src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-mutation-in-guard.rs:6:18 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- + | | | + | | move occurs because `foo` has type `&mut std::option::Option<&i32>`, which does not implement the `Copy` trait + | | move occurs due to use in closure + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs new file mode 100644 index 0000000000000..07125b98a1f7d --- /dev/null +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs @@ -0,0 +1,8 @@ +fn main() { + let a = Some("...".to_owned()); + let b = match a { + Some(_) if { drop(a); false } => None, + x => x, //~ ERROR use of moved value: `a` + }; + println!("{:?}", b); +} diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr new file mode 100644 index 0000000000000..85c83ec4d70ed --- /dev/null +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `a` + --> $DIR/issue-31287-drop-in-guard.rs:5:9 + | +LL | let a = Some("...".to_owned()); + | - move occurs because `a` has type `std::option::Option`, which does not implement the `Copy` trait +LL | let b = match a { +LL | Some(_) if { drop(a); false } => None, + | - value moved here +LL | x => x, + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. 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 c79b1873241c8..1ffb7f6fd4acd 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,9 +5,7 @@ // 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)] -#![feature(nll)] fn main() { let mut b = &mut true; 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 3a10928981c8b..a8eb78b7cc007 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:16:25 + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14: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 795a3fc210f6a..49e0dfaa3eb84 100644 --- a/src/test/ui/match/match-ref-mut-stability.rs +++ b/src/test/ui/match/match-ref-mut-stability.rs @@ -3,7 +3,7 @@ // run-pass -#![feature(nll, bind_by_move_pattern_guards)] +#![feature(bind_by_move_pattern_guards)] // Test that z always point to the same temporary. fn referent_stability() { diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index a3add8856dfa1..94e4a763866f6 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -1,7 +1,7 @@ // Test that we have enough false edges to avoid exposing the exact matching // algorithm in borrow checking. -#![feature(nll, bind_by_move_pattern_guards)] +#![feature(bind_by_move_pattern_guards)] fn guard_always_precedes_arm(y: i32) { let mut x; @@ -41,18 +41,4 @@ fn guard_may_be_taken(y: bool) { }; } -fn all_previous_tests_may_be_done(y: &mut (bool, bool)) { - let r = &mut y.1; - // We don't actually test y.1 to select the second arm, but we don't want - // borrowck results to be based on the order we match patterns. - match y { - (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed - (true, _) => { - r; - 2 - } - (false, _) => 3, - }; -} - fn main() {} diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index d37c52444ac0d..b1e0fa739769a 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -16,19 +16,7 @@ LL | true => { LL | x; | ^ value used here after move -error[E0503]: cannot use `y.1` because it was mutably borrowed - --> $DIR/match-cfg-fake-edges.rs:49:17 - | -LL | let r = &mut y.1; - | -------- borrow of `y.1` occurs here -... -LL | (false, true) => 1, - | ^^^^ use of borrowed `y.1` -LL | (true, _) => { -LL | r; - | - borrow later used here - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0381, E0382, E0503. +Some errors have detailed explanations: E0381, E0382. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/nll/match-cfg-fake-edges2.rs b/src/test/ui/nll/match-cfg-fake-edges2.rs new file mode 100644 index 0000000000000..84c0dec2fe5cd --- /dev/null +++ b/src/test/ui/nll/match-cfg-fake-edges2.rs @@ -0,0 +1,20 @@ +// Test that we have enough false edges to avoid exposing the exact matching +// algorithm in borrow checking. + +#![feature(nll)] + +fn all_previous_tests_may_be_done(y: &mut (bool, bool)) { + let r = &mut y.1; + // We don't actually test y.1 to select the second arm, but we don't want + // borrowck results to be based on the order we match patterns. + match y { + (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed + (true, _) => { + r; + 2 + } + (false, _) => 3, + }; +} + +fn main() {} diff --git a/src/test/ui/nll/match-cfg-fake-edges2.stderr b/src/test/ui/nll/match-cfg-fake-edges2.stderr new file mode 100644 index 0000000000000..eab89658e79be --- /dev/null +++ b/src/test/ui/nll/match-cfg-fake-edges2.stderr @@ -0,0 +1,15 @@ +error[E0503]: cannot use `y.1` because it was mutably borrowed + --> $DIR/match-cfg-fake-edges2.rs:11:17 + | +LL | let r = &mut y.1; + | -------- borrow of `y.1` occurs here +... +LL | (false, true) => 1, + | ^^^^ use of borrowed `y.1` +LL | (true, _) => { +LL | r; + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs index 6e158713146f1..601c46ff86cc7 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.rs +++ b/src/test/ui/nll/match-guards-partially-borrow.rs @@ -5,9 +5,7 @@ // 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)] -#![feature(nll)] fn ok_mutation_in_guard(mut q: i32) { match q { diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr index 3d9b67b4ea660..b2951fd339da4 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:59:13 + --> $DIR/match-guards-partially-borrow.rs:57: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:71:13 + --> $DIR/match-guards-partially-borrow.rs:69: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:95:13 + --> $DIR/match-guards-partially-borrow.rs:93: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:109:22 + --> $DIR/match-guards-partially-borrow.rs:107: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:121:13 + --> $DIR/match-guards-partially-borrow.rs:119: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:132:13 + --> $DIR/match-guards-partially-borrow.rs:130: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:143:13 + --> $DIR/match-guards-partially-borrow.rs:141: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:155:13 + --> $DIR/match-guards-partially-borrow.rs:153: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:166:13 + --> $DIR/match-guards-partially-borrow.rs:164: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 6e75977b5900e..e43c8541e6d6d 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 @@ -2,7 +2,7 @@ // rust-lang/rust#2329), that starts passing with this feature in // place. -// build-pass (FIXME(62277): could be check-pass?) +// run-pass #![feature(bind_by_move_pattern_guards)] @@ -12,6 +12,7 @@ fn main() { let (tx, rx) = channel(); let x = Some(rx); tx.send(false); + tx.send(false); match x { Some(z) if z.recv().unwrap() => { panic!() }, Some(z) => { assert!(!z.recv().unwrap()); }, 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 index 34e8b0e14399e..fe1f699074735 100644 --- 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 @@ -1,5 +1,5 @@ error: compilation successful - --> $DIR/feature-gate.rs:41:1 + --> $DIR/feature-gate.rs:36:1 | LL | / fn main() { LL | | foo(107) 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 index 34e8b0e14399e..fe1f699074735 100644 --- 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 @@ -1,5 +1,5 @@ error: compilation successful - --> $DIR/feature-gate.rs:41:1 + --> $DIR/feature-gate.rs:36:1 | LL | / fn main() { LL | | foo(107) 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 index c2f6edee05fa6..7a7b1c253528f 100644 --- 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 @@ -1,5 +1,5 @@ error[E0008]: cannot bind by-move into a pattern guard - --> $DIR/feature-gate.rs:33:16 + --> $DIR/feature-gate.rs:28:16 | LL | A { a: v } if *v == 42 => v, | ^ moves value into pattern guard 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 index 97f90f7762a41..69fce0bc775f7 100644 --- 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 @@ -6,7 +6,7 @@ // gate-test-bind_by_move_pattern_guards -// revisions: no_gate gate_and_2015 gate_and_2018 gate_and_znll gate_and_feature_nll +// 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 @@ -15,14 +15,9 @@ #![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))] #![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))] -#![cfg_attr(gate_and_znll, feature(bind_by_move_pattern_guards))] -#![cfg_attr(gate_and_feature_nll, feature(bind_by_move_pattern_guards))] - -#![cfg_attr(gate_and_feature_nll, feature(nll))] //[gate_and_2015] edition:2015 //[gate_and_2018] edition:2018 -//[gate_and_znll] compile-flags: -Z borrowck=mir struct A { a: Box } @@ -43,5 +38,3 @@ fn main() { } //[gate_and_2015]~^^^ ERROR compilation successful //[gate_and_2018]~^^^^ ERROR compilation successful -//[gate_and_znll]~^^^^^ ERROR compilation successful -//[gate_and_feature_nll]~^^^^^^ ERROR compilation successful 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 40588ca331eba..eccb4e417b694 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,6 +1,6 @@ #![feature(bind_by_move_pattern_guards)] -// build-pass (FIXME(62277): could be check-pass?) +// run-pass struct A { a: Box } @@ -8,32 +8,38 @@ impl A { fn get(&self) -> i32 { *self.a } } -fn foo(n: i32) { +fn foo(n: i32) -> i32 { let x = A { a: Box::new(n) }; let y = match x { A { a: v } if *v == 42 => v, _ => Box::new(0), }; + *y } -fn bar(n: i32) { +fn bar(n: i32) -> i32 { let x = A { a: Box::new(n) }; let y = match x { A { a: v } if x.get() == 42 => v, _ => Box::new(0), }; + *y } -fn baz(n: i32) { +fn baz(n: i32) -> i32 { let x = A { a: Box::new(n) }; let y = match x { A { a: v } if *v.clone() == 42 => v, _ => Box::new(0), }; + *y } fn main() { - foo(107); - bar(107); - baz(107); + assert_eq!(foo(107), 0); + assert_eq!(foo(42), 42); + assert_eq!(bar(107), 0); + assert_eq!(bar(42), 42); + assert_eq!(baz(107), 0); + assert_eq!(baz(42), 42); } 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 bf387d01b6b2e..602a8e15cb180 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,4 +1,3 @@ -#![feature(nll)] #![feature(bind_by_move_pattern_guards)] enum VecWrapper { A(Vec) } 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 f6e4e5bd49bf8..c9e8fc8ee532b 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:8:36 + --> $DIR/rfc-reject-double-move-across-arms.rs:7: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 ba999e9b3a4a3..77252a1ce1569 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,4 +1,3 @@ -#![feature(nll)] #![feature(bind_by_move_pattern_guards)] struct A { a: Box } 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 ec133b028e8f8..a345022cee7c5 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:9:30 + --> $DIR/rfc-reject-double-move-in-first-arm.rs:8: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