Auto merge of #63059 - Centril:sound-bind-by-move, r=matthewjasper

Make `#![feature(bind_by_move_pattern_guards)]` sound without `#[feature(nll)]`

Implements https://github.com/rust-lang/rust/issues/15287#issuecomment-507054617 making `#![feature(bind_by_move_pattern_guards)]]` sound without also having `#![feature(nll)]`. The logic here is that if we see a `match` guard, we will refuse to downgrade NLL errors to warnings. This is in preparation for hopefully stabilizing the former feature in https://github.com/rust-lang/rust/pull/63118.

As fall out from the implementation we also:
Fixes https://github.com/rust-lang/rust/issues/31287
Fixes https://github.com/rust-lang/rust/issues/27282

r? @matthewjasper
This commit is contained in:
bors 2019-08-03 20:11:25 +00:00
commit 6e0d27d936
35 changed files with 205 additions and 186 deletions

View file

@ -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() }
}

View file

@ -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;

View file

@ -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) {

View file

@ -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 => (),

View file

@ -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<Pat>]) {
fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
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<Pat>],
) {
@ -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<Span>| {
let check_move = |
cx: &mut MatchVisitor<'_, '_>,
p: &Pat,
sub: Option<&Pat>,
span_vec: &mut Vec<Span>,
| {
// 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);
}
}
_ => {}

View file

@ -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`

View file

@ -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() {}

View file

@ -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`

View file

@ -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`.

View file

@ -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,
}

View file

@ -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`.

View file

@ -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."),
}
}

View file

@ -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`.

View file

@ -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);
}

View file

@ -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<std::string::String>`, 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`.

View file

@ -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;

View file

@ -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

View file

@ -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() {

View file

@ -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() {}

View file

@ -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 2 previous errors
error: aborting due to 3 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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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 {

View file

@ -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

View file

@ -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()); },

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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<i32> }
@ -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

View file

@ -1,6 +1,6 @@
#![feature(bind_by_move_pattern_guards)]
// build-pass (FIXME(62277): could be check-pass?)
// run-pass
struct A { a: Box<i32> }
@ -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);
}

View file

@ -1,4 +1,3 @@
#![feature(nll)]
#![feature(bind_by_move_pattern_guards)]
enum VecWrapper { A(Vec<i32>) }

View file

@ -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<i32>`, which does not implement the `Copy` trait

View file

@ -1,4 +1,3 @@
#![feature(nll)]
#![feature(bind_by_move_pattern_guards)]
struct A { a: Box<i32> }

View file

@ -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<i32>`, which does not implement the `Copy` trait

View file

@ -50,7 +50,7 @@ const TEST_REPOS: &'static [Test] = &[
Test {
name: "servo",
repo: "https://github.com/servo/servo",
sha: "987e376ca7a4245dbc3e0c06e963278ee1ac92d1",
sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
lock: None,
// Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
// This takes much less time to build than all of Servo and supports stable Rust.