Test the borrowck behavior of if-let guards

This commit is contained in:
Léo Lanteri Thauvin 2022-12-21 16:29:35 +01:00
parent 1d12c3cea3
commit 56aaf749b6
27 changed files with 647 additions and 64 deletions

View File

@ -1,3 +1,5 @@
#![feature(if_let_guard)]
fn foo(_:String) {}
fn main()
@ -8,4 +10,11 @@ fn main()
Some(_) => {}
None => { foo(my_str); } //~ ERROR [E0382]
}
let my_str = "hello".to_owned();
match Some(42) {
Some(_) if let Some(()) = { drop(my_str); None } => {}
Some(_) => {}
None => { foo(my_str); } //~ ERROR [E0382]
}
}

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value: `my_str`
--> $DIR/borrowck-drop-from-guard.rs:9:23
--> $DIR/borrowck-drop-from-guard.rs:11:23
|
LL | let my_str = "hello".to_owned();
| ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait
@ -15,6 +15,23 @@ help: consider cloning the value if the performance cost is acceptable
LL | Some(_) if { drop(my_str.clone()); false } => {}
| ++++++++
error: aborting due to previous error
error[E0382]: use of moved value: `my_str`
--> $DIR/borrowck-drop-from-guard.rs:18:23
|
LL | let my_str = "hello".to_owned();
| ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait
LL | match Some(42) {
LL | Some(_) if let Some(()) = { drop(my_str); None } => {}
| ------ value moved here
LL | Some(_) => {}
LL | None => { foo(my_str); }
| ^^^^^^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | Some(_) if let Some(()) = { drop(my_str.clone()); None } => {}
| ++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.

View File

@ -1,9 +1,11 @@
#![feature(if_let_guard)]
enum Enum<'a> {
A(&'a isize),
B(bool),
}
fn foo() -> isize {
fn if_guard() -> isize {
let mut n = 42;
let mut x = Enum::A(&mut n);
match x {
@ -16,6 +18,17 @@ fn foo() -> isize {
}
}
fn main() {
foo();
fn if_let_guard() -> isize {
let mut n = 42;
let mut x = Enum::A(&mut n);
match x {
Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1,
//~^ ERROR cannot assign `x` in match guard
Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1,
//~^ ERROR cannot mutably borrow `x` in match guard
Enum::A(p) => *p,
Enum::B(_) => 2,
}
}
fn main() {}

View File

@ -1,5 +1,5 @@
error[E0510]: cannot assign `x` in match guard
--> $DIR/borrowck-mutate-in-guard.rs:10:25
--> $DIR/borrowck-mutate-in-guard.rs:12:25
|
LL | match x {
| - value is immutable in match guard
@ -7,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:12:33
--> $DIR/borrowck-mutate-in-guard.rs:14:33
|
LL | match x {
| - value is immutable in match guard
@ -15,6 +15,23 @@ LL | match x {
LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
| ^^^^^^ cannot mutably borrow
error: aborting due to 2 previous errors
error[E0510]: cannot assign `x` in match guard
--> $DIR/borrowck-mutate-in-guard.rs:25:40
|
LL | match x {
| - value is immutable in match guard
LL | Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1,
| ^^^^^^^^^^^^^^^^^^ cannot assign
error[E0510]: cannot mutably borrow `x` in match guard
--> $DIR/borrowck-mutate-in-guard.rs:27:48
|
LL | match x {
| - value is immutable in match guard
...
LL | Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1,
| ^^^^^^ cannot mutably borrow
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0510`.

View File

@ -1,8 +1,15 @@
#![feature(if_let_guard)]
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);
let a = Some("...".to_owned());
let b = match a {
Some(_) if let Some(()) = { drop(a); None } => None,
x => x, //~ ERROR use of moved value: `a`
};
}

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value: `a`
--> $DIR/issue-31287-drop-in-guard.rs:5:9
--> $DIR/issue-31287-drop-in-guard.rs:7:9
|
LL | let a = Some("...".to_owned());
| - move occurs because `a` has type `Option<String>`, which does not implement the `Copy` trait
@ -14,6 +14,22 @@ help: consider cloning the value if the performance cost is acceptable
LL | Some(_) if { drop(a.clone()); false } => None,
| ++++++++
error: aborting due to previous error
error[E0382]: use of moved value: `a`
--> $DIR/issue-31287-drop-in-guard.rs:13:9
|
LL | let a = Some("...".to_owned());
| - move occurs because `a` has type `Option<String>`, which does not implement the `Copy` trait
LL | let b = match a {
LL | Some(_) if let Some(()) = { drop(a); None } => None,
| - value moved here
LL | x => x,
| ^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | Some(_) if let Some(()) = { drop(a.clone()); None } => None,
| ++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.

View File

@ -1,5 +1,7 @@
// test for https://github.com/rust-lang/rust/issues/29723
#![feature(if_let_guard)]
fn main() {
let s = String::new();
let _s = match 0 {
@ -11,4 +13,10 @@ fn main() {
//~^ ERROR use of moved value: `s`
}
};
let s = String::new();
let _s = match 0 {
0 if let Some(()) = { drop(s); None } => String::from("oops"),
_ => s //~ ERROR use of moved value: `s`
};
}

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value: `s`
--> $DIR/issue-29723.rs:10:13
--> $DIR/issue-29723.rs:12:13
|
LL | let s = String::new();
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
@ -15,6 +15,22 @@ help: consider cloning the value if the performance cost is acceptable
LL | 0 if { drop(s.clone()); false } => String::from("oops"),
| ++++++++
error: aborting due to previous error
error[E0382]: use of moved value: `s`
--> $DIR/issue-29723.rs:20:14
|
LL | let s = String::new();
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
LL | let _s = match 0 {
LL | 0 if let Some(()) = { drop(s); None } => String::from("oops"),
| - value moved here
LL | _ => s
| ^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | 0 if let Some(()) = { drop(s.clone()); None } => String::from("oops"),
| ++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.

View File

@ -5,6 +5,8 @@
// See further discussion on rust-lang/rust#24535,
// rust-lang/rfcs#1006, and rust-lang/rfcs#107
#![feature(if_let_guard)]
fn main() {
rust_issue_24535();
rfcs_issue_1006_1();
@ -23,6 +25,12 @@ fn compare(a: &u8, b: &mut u8) -> bool {
3 if compare(&a, &mut 3) => (),
_ => panic!("nope"),
}
match a {
0 => panic!("nope"),
3 if let true = compare(&a, &mut 3) => (),
_ => panic!("nope"),
}
}
fn rfcs_issue_1006_1() {

View File

@ -7,6 +7,8 @@
// reaches the panic code when executed, despite the compiler warning
// about that match arm being unreachable.
#![feature(if_let_guard)]
fn main() {
let b = &mut true;
match b {
@ -17,4 +19,16 @@ fn main() {
&mut true => { println!("You might think we should get here"); },
_ => panic!("surely we could never get here, since rustc warns it is unreachable."),
}
let b = &mut true;
match b {
//~^ ERROR use of moved value: `b` [E0382]
&mut false => {}
_ if let Some(()) = {
(|| { let bar = b; *bar = false; })();
None
} => {}
&mut true => {}
_ => {}
}
}

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value: `b`
--> $DIR/issue-27282-move-match-input-into-guard.rs:12:5
--> $DIR/issue-27282-move-match-input-into-guard.rs:14:5
|
LL | let b = &mut true;
| - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
@ -11,6 +11,19 @@ LL | _ if { (|| { let bar = b; *bar = false; })();
| |
| value moved into closure here
error: aborting due to previous error
error[E0382]: use of moved value: `b`
--> $DIR/issue-27282-move-match-input-into-guard.rs:24:5
|
LL | let b = &mut true;
| - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
LL | match b {
| ^^^^^^^ value used here after move
...
LL | (|| { let bar = b; *bar = false; })();
| -- - variable moved due to use in closure
| |
| value moved into closure here
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.

View File

@ -2,6 +2,8 @@
// mutable borrows in match guards by hiding the mutable borrow in a
// guard behind a move (of the ref mut pattern id) within a closure.
#![feature(if_let_guard)]
fn main() {
match Some(&4) {
None => {},
@ -10,4 +12,12 @@ fn main() {
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
ref mut foo
if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
Some(s) => std::process::exit(*s),
}
}

View File

@ -1,5 +1,5 @@
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19
|
LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@ -8,6 +8,16 @@ LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to previous error
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
|
LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| 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 2 previous errors
For more information about this error, try `rustc --explain E0507`.

View File

@ -1,3 +1,5 @@
#![feature(if_let_guard)]
fn main() {
match Some(&4) {
None => {},
@ -10,4 +12,15 @@ fn main() {
Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
_ => println!("Here is some supposedly unreachable code."),
}
match Some(&4) {
None => {},
ref mut foo
if let Some(()) = {
(|| { let bar = foo; bar.take() })();
//~^ ERROR cannot move out of `foo` in pattern guard
None
} => {},
Some(_) => {},
}
}

View File

@ -1,5 +1,5 @@
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-mutation-in-guard.rs:6:18
--> $DIR/issue-27282-mutation-in-guard.rs:8:18
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })();
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to previous error
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-mutation-in-guard.rs:20:18
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| 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 2 previous errors
For more information about this error, try `rustc --explain E0507`.

View File

@ -3,7 +3,9 @@
// It reborrows instead of moving the `ref mut` pattern borrow. This
// means that our conservative check for mutation in guards will
// reject it. But I want to make sure that we continue to reject it
// (under NLL) even when that conservaive check goes away.
// (under NLL) even when that conservative check goes away.
#![feature(if_let_guard)]
fn main() {
let mut b = &mut true;
@ -15,4 +17,14 @@ fn main() {
&mut true => { println!("You might think we should get here"); },
_ => panic!("surely we could never get here, since rustc warns it is unreachable."),
}
let mut b = &mut true;
match b {
&mut false => {},
ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })();
//~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard
None } => { &mut *r; },
&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:12: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
@ -8,6 +8,16 @@ LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
|
= note: variables bound in patterns are immutable until the end of the pattern guard
error: aborting due to previous error
error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
--> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:24:40
|
LL | ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })();
| ^^ -- mutable borrow occurs due to use of `r` in closure
| |
| 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
For more information about this error, try `rustc --explain E0596`.

View File

@ -1,6 +1,8 @@
// Test that we have enough false edges to avoid exposing the exact matching
// algorithm in borrow checking.
#![feature(if_let_guard)]
fn guard_always_precedes_arm(y: i32) {
let mut x;
// x should always be initialized, as the only way to reach the arm is
@ -9,6 +11,12 @@ fn guard_always_precedes_arm(y: i32) {
0 | 2 if { x = 2; true } => x,
_ => 2,
};
let mut x;
match y {
0 | 2 if let Some(()) = { x = 2; Some(()) } => x,
_ => 2,
};
}
fn guard_may_be_skipped(y: i32) {
@ -23,6 +31,16 @@ fn guard_may_be_skipped(y: i32) {
} => 2,
_ => 3,
};
let x;
match y {
_ if let Some(()) = { x = 2; Some(()) } => 1,
_ if let Some(()) = {
x; //~ ERROR E0381
None
} => 2,
_ => 3,
};
}
fn guard_may_be_taken(y: bool) {
@ -37,6 +55,16 @@ fn guard_may_be_taken(y: bool) {
}
false => 3,
};
let x = String::new();
match y {
false if let Some(()) = { drop(x); Some(()) } => 1,
true => {
x; //~ ERROR use of moved value: `x`
2
}
false => 3,
};
}
fn main() {}

View File

@ -1,5 +1,5 @@
error[E0381]: used binding `x` isn't initialized
--> $DIR/match-cfg-fake-edges.rs:21:13
--> $DIR/match-cfg-fake-edges.rs:29:13
|
LL | let x;
| - binding declared here but left uninitialized
@ -15,8 +15,25 @@ help: consider assigning a value
LL | let x = 0;
| +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/match-cfg-fake-edges.rs:39:13
|
LL | let x;
| - binding declared here but left uninitialized
LL | match y {
LL | _ if let Some(()) = { x = 2; Some(()) } => 1,
| ----- binding initialized here in some conditions
LL | _ if let Some(()) = {
LL | x;
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
LL | let x = 0;
| +++
error[E0382]: use of moved value: `x`
--> $DIR/match-cfg-fake-edges.rs:35:13
--> $DIR/match-cfg-fake-edges.rs:53:13
|
LL | let x = String::new();
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
@ -32,7 +49,24 @@ help: consider cloning the value if the performance cost is acceptable
LL | false if { drop(x.clone()); true } => 1,
| ++++++++
error: aborting due to 2 previous errors
error[E0382]: use of moved value: `x`
--> $DIR/match-cfg-fake-edges.rs:63:13
|
LL | let x = String::new();
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
LL | match y {
LL | false if let Some(()) = { drop(x); Some(()) } => 1,
| - value moved here
LL | true => {
LL | x;
| ^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | false if let Some(()) = { drop(x.clone()); Some(()) } => 1,
| ++++++++
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0381, E0382.
For more information about an error, try `rustc --explain E0381`.

View File

@ -1,3 +1,5 @@
#![feature(if_let_guard)]
// Here is arielb1's basic example from rust-lang/rust#27282
// that AST borrowck is flummoxed by:
@ -10,6 +12,15 @@ fn should_reject_destructive_mutate_in_guard() {
false } => { },
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
ref mut foo if let Some(()) = {
(|| { let bar = foo; bar.take() })();
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
None } => { },
Some(s) => std::process::exit(*s),
}
}
// Here below is a case that needs to keep working: we only use the
@ -18,7 +29,13 @@ fn should_reject_destructive_mutate_in_guard() {
fn allow_mutate_in_arm_body() {
match Some(&4) {
None => {},
ref mut foo if foo.is_some() && false => { foo.take(); () }
ref mut foo if foo.is_some() => { foo.take(); () }
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
ref mut foo if let Some(_) = foo => { foo.take(); () }
Some(s) => std::process::exit(*s),
}
}
@ -29,7 +46,13 @@ fn allow_mutate_in_arm_body() {
fn allow_move_into_arm_body() {
match Some(&4) {
None => {},
mut foo if foo.is_some() && false => { foo.take(); () }
mut foo if foo.is_some() => { foo.unwrap(); () }
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
mut foo if let Some(_) = foo => { foo.unwrap(); () }
Some(s) => std::process::exit(*s),
}
}

View File

@ -1,5 +1,5 @@
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/match-guards-always-borrow.rs:8:14
--> $DIR/match-guards-always-borrow.rs:10:14
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })();
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to previous error
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/match-guards-always-borrow.rs:19:14
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| 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 2 previous errors
For more information about this error, try `rustc --explain E0507`.

View File

@ -5,7 +5,9 @@
// 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.
fn ok_mutation_in_guard(mut q: i32) {
#![feature(if_let_guard)]
fn ok_mutation_in_if_guard(mut q: i32) {
match q {
// OK, mutation doesn't change which patterns g matches
_ if { q = 1; false } => (),
@ -13,7 +15,15 @@ fn ok_mutation_in_guard(mut q: i32) {
}
}
fn ok_mutation_in_guard2(mut u: bool) {
fn ok_mutation_in_if_let_guard(mut q: i32) {
match q {
// OK, mutation doesn't change which patterns g matches
_ if let Some(()) = { q = 1; None } => (),
_ => (),
}
}
fn ok_mutation_in_if_guard2(mut u: bool) {
// OK value of u is unused before modification
match u {
_ => (),
@ -25,7 +35,19 @@ fn ok_mutation_in_guard2(mut u: bool) {
}
}
fn ok_mutation_in_guard4(mut w: (&mut bool,)) {
fn ok_mutation_in_if_let_guard2(mut u: bool) {
// OK value of u is unused before modification
match u {
_ => (),
_ if let Some(()) = {
u = true;
None
} => (),
x => (),
}
}
fn ok_mutation_in_if_guard4(mut w: (&mut bool,)) {
// OK value of u is unused before modification
match w {
_ => (),
@ -37,7 +59,19 @@ fn ok_mutation_in_guard4(mut w: (&mut bool,)) {
}
}
fn ok_indirect_mutation_in_guard(mut p: &bool) {
fn ok_mutation_in_if_let_guard4(mut w: (&mut bool,)) {
// OK value of u is unused before modification
match w {
_ => (),
_ if let Some(()) = {
*w.0 = true;
None
} => (),
x => (),
}
}
fn ok_indirect_mutation_in_if_guard(mut p: &bool) {
match *p {
// OK, mutation doesn't change which patterns s matches
_ if {
@ -48,7 +82,18 @@ fn ok_indirect_mutation_in_guard(mut p: &bool) {
}
}
fn mutation_invalidates_pattern_in_guard(mut q: bool) {
fn ok_indirect_mutation_in_if_let_guard(mut p: &bool) {
match *p {
// OK, mutation doesn't change which patterns s matches
_ if let Some(()) = {
p = &true;
None
} => (),
_ => (),
}
}
fn mutation_invalidates_pattern_in_if_guard(mut q: bool) {
match q {
// q doesn't match the pattern with the guard by the end of the guard.
false if {
@ -59,7 +104,18 @@ fn mutation_invalidates_pattern_in_guard(mut q: bool) {
}
}
fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
fn mutation_invalidates_pattern_in_if_let_guard(mut q: bool) {
match q {
// q doesn't match the pattern with the guard by the end of the guard.
false if let Some(()) = {
q = true; //~ ERROR
Some(())
} => (),
_ => (),
}
}
fn mutation_invalidates_previous_pattern_in_if_guard(mut r: bool) {
match r {
// r matches a previous pattern by the end of the guard.
true => (),
@ -71,7 +127,19 @@ fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
}
}
fn match_on_borrowed_early_end(mut s: bool) {
fn mutation_invalidates_previous_pattern_in_if_let_guard(mut r: bool) {
match r {
// r matches a previous pattern by the end of the guard.
true => (),
_ if let Some(()) = {
r = true; //~ ERROR
Some(())
} => (),
_ => (),
}
}
fn match_on_borrowed_early_end_if_guard(mut s: bool) {
let h = &mut s;
// OK value of s is unused before modification.
match s {
@ -84,7 +152,20 @@ fn match_on_borrowed_early_end(mut s: bool) {
}
}
fn bad_mutation_in_guard(mut t: bool) {
fn match_on_borrowed_early_end_if_let_guard(mut s: bool) {
let h = &mut s;
// OK value of s is unused before modification.
match s {
_ if let Some(()) = {
*h = !*h;
None
} => (),
true => (),
false => (),
}
}
fn bad_mutation_in_if_guard(mut t: bool) {
match t {
true => (),
false if {
@ -95,7 +176,18 @@ fn bad_mutation_in_guard(mut t: bool) {
}
}
fn bad_mutation_in_guard2(mut x: Option<Option<&i32>>) {
fn bad_mutation_in_if_let_guard(mut t: bool) {
match t {
true => (),
false if let Some(()) = {
t = true; //~ ERROR
None
} => (),
false => (),
}
}
fn bad_mutation_in_if_guard2(mut x: Option<Option<&i32>>) {
// Check that nested patterns are checked.
match x {
None => (),
@ -111,7 +203,23 @@ fn bad_mutation_in_guard2(mut x: Option<Option<&i32>>) {
}
}
fn bad_mutation_in_guard3(mut t: bool) {
fn bad_mutation_in_if_let_guard2(mut x: Option<Option<&i32>>) {
// Check that nested patterns are checked.
match x {
None => (),
Some(None) => (),
_ if let Some(()) = {
match x {
Some(ref mut r) => *r = None, //~ ERROR
_ => return,
};
None
} => (),
Some(Some(r)) => println!("{}", r),
}
}
fn bad_mutation_in_if_guard3(mut t: bool) {
match t {
s if {
t = !t; //~ ERROR
@ -121,7 +229,17 @@ fn bad_mutation_in_guard3(mut t: bool) {
}
}
fn bad_indirect_mutation_in_guard(mut y: &bool) {
fn bad_mutation_in_if_let_guard3(mut t: bool) {
match t {
s if let Some(()) = {
t = !t; //~ ERROR
None
} => (), // What value should `s` have in the arm?
_ => (),
}
}
fn bad_indirect_mutation_in_if_guard(mut y: &bool) {
match *y {
true => (),
false if {
@ -132,7 +250,18 @@ fn bad_indirect_mutation_in_guard(mut y: &bool) {
}
}
fn bad_indirect_mutation_in_guard2(mut z: &bool) {
fn bad_indirect_mutation_in_if_let_guard(mut y: &bool) {
match *y {
true => (),
false if let Some(()) = {
y = &true; //~ ERROR
None
} => (),
false => (),
}
}
fn bad_indirect_mutation_in_if_guard2(mut z: &bool) {
match z {
&true => (),
&false if {
@ -143,8 +272,19 @@ fn bad_indirect_mutation_in_guard2(mut z: &bool) {
}
}
fn bad_indirect_mutation_in_guard3(mut a: &bool) {
// Same as bad_indirect_mutation_in_guard2, but using match ergonomics
fn bad_indirect_mutation_in_if_let_guard2(mut z: &bool) {
match z {
&true => (),
&false if let Some(()) = {
z = &true; //~ ERROR
None
} => (),
&false => (),
}
}
fn bad_indirect_mutation_in_if_guard3(mut a: &bool) {
// Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics
match a {
true => (),
false if {
@ -155,7 +295,19 @@ fn bad_indirect_mutation_in_guard3(mut a: &bool) {
}
}
fn bad_indirect_mutation_in_guard4(mut b: &bool) {
fn bad_indirect_mutation_in_if_let_guard3(mut a: &bool) {
// Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics
match a {
true => (),
false if let Some(()) = {
a = &true; //~ ERROR
None
} => (),
false => (),
}
}
fn bad_indirect_mutation_in_if_guard4(mut b: &bool) {
match b {
&_ => (),
&_ if {
@ -166,4 +318,15 @@ fn bad_indirect_mutation_in_guard4(mut b: &bool) {
}
}
fn bad_indirect_mutation_in_if_let_guard4(mut b: &bool) {
match b {
&_ => (),
&_ if let Some(()) = {
b = &true; //~ ERROR
None
} => (),
&b => (),
}
}
fn main() {}

View File

@ -1,5 +1,14 @@
error[E0510]: cannot assign `q` in match guard
--> $DIR/match-guards-partially-borrow.rs:55:13
--> $DIR/match-guards-partially-borrow.rs:100:13
|
LL | match q {
| - value is immutable in match guard
...
LL | q = true;
| ^^^^^^^^ cannot assign
error[E0510]: cannot assign `q` in match guard
--> $DIR/match-guards-partially-borrow.rs:111:13
|
LL | match q {
| - value is immutable in match guard
@ -8,7 +17,16 @@ LL | q = true;
| ^^^^^^^^ cannot assign
error[E0510]: cannot assign `r` in match guard
--> $DIR/match-guards-partially-borrow.rs:67:13
--> $DIR/match-guards-partially-borrow.rs:123:13
|
LL | match r {
| - value is immutable in match guard
...
LL | r = true;
| ^^^^^^^^ cannot assign
error[E0510]: cannot assign `r` in match guard
--> $DIR/match-guards-partially-borrow.rs:135:13
|
LL | match r {
| - value is immutable in match guard
@ -17,7 +35,16 @@ LL | r = true;
| ^^^^^^^^ cannot assign
error[E0510]: cannot assign `t` in match guard
--> $DIR/match-guards-partially-borrow.rs:91:13
--> $DIR/match-guards-partially-borrow.rs:172:13
|
LL | match t {
| - value is immutable in match guard
...
LL | t = true;
| ^^^^^^^^ cannot assign
error[E0510]: cannot assign `t` in match guard
--> $DIR/match-guards-partially-borrow.rs:183:13
|
LL | match t {
| - value is immutable in match guard
@ -26,7 +53,16 @@ LL | t = true;
| ^^^^^^^^ cannot assign
error[E0510]: cannot mutably borrow `x.0` in match guard
--> $DIR/match-guards-partially-borrow.rs:105:22
--> $DIR/match-guards-partially-borrow.rs:197:22
|
LL | match x {
| - value is immutable in match guard
...
LL | Some(ref mut r) => *r = None,
| ^^^^^^^^^ cannot mutably borrow
error[E0510]: cannot mutably borrow `x.0` in match guard
--> $DIR/match-guards-partially-borrow.rs:213:22
|
LL | match x {
| - value is immutable in match guard
@ -35,7 +71,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:117:13
--> $DIR/match-guards-partially-borrow.rs:225:13
|
LL | s if {
| - borrow of `t` occurs here
@ -45,8 +81,28 @@ LL | false
LL | } => (), // What value should `s` have in the arm?
| - borrow later used here
error[E0506]: cannot assign to `t` because it is borrowed
--> $DIR/match-guards-partially-borrow.rs:235:13
|
LL | s if let Some(()) = {
| - borrow of `t` occurs here
LL | t = !t;
| ^^^^^^ assignment to borrowed `t` occurs here
LL | None
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:128:13
--> $DIR/match-guards-partially-borrow.rs:246:13
|
LL | match *y {
| -- value is immutable in match guard
...
LL | y = &true;
| ^^^^^^^^^ cannot assign
error[E0510]: cannot assign `y` in match guard
--> $DIR/match-guards-partially-borrow.rs:257:13
|
LL | match *y {
| -- value is immutable in match guard
@ -55,7 +111,16 @@ LL | y = &true;
| ^^^^^^^^^ cannot assign
error[E0510]: cannot assign `z` in match guard
--> $DIR/match-guards-partially-borrow.rs:139:13
--> $DIR/match-guards-partially-borrow.rs:268:13
|
LL | match z {
| - value is immutable in match guard
...
LL | z = &true;
| ^^^^^^^^^ cannot assign
error[E0510]: cannot assign `z` in match guard
--> $DIR/match-guards-partially-borrow.rs:279:13
|
LL | match z {
| - value is immutable in match guard
@ -64,7 +129,16 @@ LL | z = &true;
| ^^^^^^^^^ cannot assign
error[E0510]: cannot assign `a` in match guard
--> $DIR/match-guards-partially-borrow.rs:151:13
--> $DIR/match-guards-partially-borrow.rs:291:13
|
LL | match a {
| - value is immutable in match guard
...
LL | a = &true;
| ^^^^^^^^^ cannot assign
error[E0510]: cannot assign `a` in match guard
--> $DIR/match-guards-partially-borrow.rs:303:13
|
LL | match a {
| - value is immutable in match guard
@ -73,7 +147,7 @@ LL | a = &true;
| ^^^^^^^^^ cannot assign
error[E0510]: cannot assign `b` in match guard
--> $DIR/match-guards-partially-borrow.rs:162:13
--> $DIR/match-guards-partially-borrow.rs:314:13
|
LL | match b {
| - value is immutable in match guard
@ -81,7 +155,16 @@ LL | match b {
LL | b = &true;
| ^^^^^^^^^ cannot assign
error: aborting due to 9 previous errors
error[E0510]: cannot assign `b` in match guard
--> $DIR/match-guards-partially-borrow.rs:325:13
|
LL | match b {
| - value is immutable in match guard
...
LL | b = &true;
| ^^^^^^^^^ cannot assign
error: aborting due to 18 previous errors
Some errors have detailed explanations: E0506, E0510.
For more information about an error, try `rustc --explain E0506`.

View File

@ -1,6 +1,8 @@
#![feature(if_let_guard)]
enum VecWrapper { A(Vec<i32>) }
fn foo(x: VecWrapper) -> usize {
fn if_guard(x: VecWrapper) -> usize {
match x {
VecWrapper::A(v) if { drop(v); false } => 1,
//~^ ERROR cannot move out of `v` in pattern guard
@ -8,6 +10,15 @@ fn foo(x: VecWrapper) -> usize {
}
}
fn main() {
foo(VecWrapper::A(vec![107]));
fn if_let_guard(x: VecWrapper) -> usize {
match x {
VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
//~^ ERROR cannot move out of `v` in pattern guard
VecWrapper::A(v) => v.len()
}
}
fn main() {
if_guard(VecWrapper::A(vec![107]));
if_let_guard(VecWrapper::A(vec![107]));
}

View File

@ -1,11 +1,19 @@
error[E0507]: cannot move out of `v` in pattern guard
--> $DIR/rfc-reject-double-move-across-arms.rs:5: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 `Vec<i32>`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to previous error
error[E0507]: cannot move out of `v` in pattern guard
--> $DIR/rfc-reject-double-move-across-arms.rs:15:51
|
LL | VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
| ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0507`.

View File

@ -1,6 +1,8 @@
#![feature(if_let_guard)]
struct A { a: Box<i32> }
fn foo(n: i32) {
fn if_guard(n: i32) {
let x = A { a: Box::new(n) };
let _y = match x {
A { a: v } if { drop(v); true } => v,
@ -9,6 +11,16 @@ fn foo(n: i32) {
};
}
fn main() {
foo(107);
fn if_let_guard(n: i32) {
let x = A { a: Box::new(n) };
let _y = match x {
A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
//~^ ERROR cannot move out of `v` in pattern guard
_ => Box::new(0),
};
}
fn main() {
if_guard(107);
if_let_guard(107);
}

View File

@ -1,11 +1,19 @@
error[E0507]: cannot move out of `v` in pattern guard
--> $DIR/rfc-reject-double-move-in-first-arm.rs:6: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 `Box<i32>`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to previous error
error[E0507]: cannot move out of `v` in pattern guard
--> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45
|
LL | A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
| ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0507`.