rust/tests/ui/nll/match-guards-partially-borrow.rs
2023-01-11 09:32:08 +00:00

333 lines
7.2 KiB
Rust

// Test that a (partially) mutably borrowed place can be matched on, so long as
// we don't have to read any values that are mutably borrowed to determine
// which arm to take.
//
// 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(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 } => (),
_ => (),
}
}
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 {
_ => (),
_ if {
u = true;
false
} => (),
x => (),
}
}
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 {
_ => (),
_ if {
*w.0 = true;
false
} => (),
x => (),
}
}
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 {
p = &true;
false
} => (),
_ => (),
}
}
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 {
q = true; //~ ERROR
true
} => (),
_ => (),
}
}
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 => (),
_ if {
r = true; //~ ERROR
true
} => (),
_ => (),
}
}
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 {
_ if {
*h = !*h;
false
} => (),
true => (),
false => (),
}
}
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 {
t = true; //~ ERROR
false
} => (),
false => (),
}
}
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 => (),
Some(None) => (),
_ if {
match x {
Some(ref mut r) => *r = None, //~ ERROR
_ => return,
};
false
} => (),
Some(Some(r)) => println!("{}", r),
}
}
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
false
} => (), // What value should `s` have in the arm?
_ => (),
}
}
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 {
y = &true; //~ ERROR
false
} => (),
false => (),
}
}
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 {
z = &true; //~ ERROR
false
} => (),
&false => (),
}
}
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 {
a = &true; //~ ERROR
false
} => (),
false => (),
}
}
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 {
b = &true; //~ ERROR
false
} => (),
&b => (),
}
}
fn bad_indirect_mutation_in_if_let_guard4(mut b: &bool) {
match b {
&_ => (),
&_ if let Some(()) = {
b = &true; //~ ERROR
None
} => (),
&b => (),
}
}
fn main() {}