Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upPattern guard can consume value that is being matched #31287
Comments
apasel422
added
the
I-unsound 💥
label
Jan 29, 2016
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
triage: T-lang I-nominated I thought we fixed this :( |
alexcrichton
added
I-nominated
T-lang
labels
Jan 29, 2016
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton unfortunately no. I fixed a very similar issue involving multiple guards, but not this case. I did try to fix it, but it essentially requires SEME to work. This is because preventing this case introduces edges between successive patterns in the CFG and consequentially causes code like this:
to be rejected because the borrow in the first pattern overlaps the borrow in the second pattern. The reason why this has to be this way is because both move checking and borrow checking are done using the CFG, right now the CFG for a match "visits" all the arms in parallel, with pattern guards chaining into each other where appropriate. Improving it further requires chaining from the guard to the next pattern instead, but also requires indicating that the borrow in the pattern ends at both the "else" branch of the guard and the end of the block for the arm. In other words, we need regions with multiple exits aka SEME. |
This comment has been minimized.
This comment has been minimized.
|
Can't we just borrow the discriminant in all guards separately (cc @pnkfelix)? Actually, that might cause conflicts with This issue won't be really fixed with MIR if we are talking about bypassing-exhaustiveness rather than |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 did you accidentally comment on the wrong issue? I'm not sure how discriminants and exhaustiveness come in here. |
This comment has been minimized.
This comment has been minimized.
|
triage: P-high |
rust-highfive
added
P-high
and removed
I-nominated
labels
Feb 18, 2016
This comment has been minimized.
This comment has been minimized.
|
I think this is one of those "fixed by moving region/borrowck to MIR" |
nikomatsakis
assigned
pnkfelix
Apr 7, 2016
brson
added
the
I-crash
label
Jun 23, 2016
This comment has been minimized.
This comment has been minimized.
|
@pnkfelix Is this still on your radar? It's been assigned a while. |
brson
added
the
I-nominated
label
Jul 14, 2016
This comment has been minimized.
This comment has been minimized.
|
@rust-lang/lang nominated for retriage. Still looks bad. Can we make progress now? |
This comment has been minimized.
This comment has been minimized.
|
As an update, still segfaults both on normal and MIR trans (example above) |
aturon
added
T-compiler
and removed
T-lang
labels
Jul 14, 2016
This comment has been minimized.
This comment has been minimized.
|
Moving to compiler team; we believe this is blocked on MIR borrowck. |
pnkfelix
removed their assignment
Jul 21, 2016
This comment has been minimized.
This comment has been minimized.
|
triage: P-medium |
rust-highfive
added
P-medium
and removed
I-nominated
P-high
labels
Jul 21, 2016
TimNN
referenced this issue
Nov 20, 2016
Closed
Borrow checker permits use after move in if statements #37891
This comment has been minimized.
This comment has been minimized.
|
After some discussion in @rust-lang/compiler, the consensus was that we should increase the priority of this issue. The preferred fix is still MIR borrowck. Assigning to @pnkfelix as he has been doing work in that direction. triage: P-high |
rust-highfive
added
P-high
and removed
P-medium
labels
Dec 1, 2016
nikomatsakis
assigned
pnkfelix
Dec 1, 2016
This comment has been minimized.
This comment has been minimized.
|
Reproducer without matching on the discriminant: fn main() {
let x = Box::new(0);
match () {
_ if { drop(x); false } => {}
() => println!("{:?}", x)
}
} |
This comment has been minimized.
This comment has been minimized.
|
Related example from #37891; here the fn main() {
let vec = get_vec();
if let Err(err) = Ok::<_, ()>(1) {
println!("Got an error: {:?}", err);
}
else if vec.unwrap().len() == 0 {
println!("Vec was 0 length.");
}
else {
for i in vec.unwrap() {
println!("{}", i);
}
}
}
fn get_vec() -> Result<Vec<i32>, i32> {
Ok::<Vec<i32>, i32>(vec![1,2,3])
} |
This comment has been minimized.
This comment has been minimized.
|
triage: P-medium We decided that having this P-high wasn't really proper, since although we're actively working on a fix, it's via MIR borrowck, and not really a "drop everything" sort of situation. |
rust-highfive
added
P-medium
and removed
P-high
labels
Dec 29, 2016
This comment has been minimized.
This comment has been minimized.
scooter-dangle
commented
Jan 10, 2017
•
|
There's a weird facet to this issue that so far I haven't seen mentioned (unless I've just totally overlooked it). Playing with the code from @insanitybit's Golang and Rustlang Memory Safety, I found that inserting a I (and the several other more experienced Rustaceans I discussed this with at Rust DC) was surprised that a legal read-only use of the variable affected behavior after where it should have been dropped. This could make quirks arising from the actual issue far more difficult to debug and could possibly hide them from showing up until production if there are debug-only I wasn't sure whether to post this here or to #29723 fn main() {
let foo = String::from("FOO");
// The addition of this line prevents the subsequent `println!` from
// printing out garbage data.
println!("1: {:?}", foo);
let foo2 = match 0 {
0 if {
some_func(foo) // foo is freed here
} => unreachable!(),
_ => {
// Use After Free - we return freed memory
foo
}
};
println!("2: {:?}", foo2); // And here we access the invalid memory
}
fn some_func(foo: String) -> bool {
drop(foo);
false
}prints out
|
This comment has been minimized.
This comment has been minimized.
samueltardieu
commented
Jan 10, 2017
|
I find the proof of the corruption even more stunning if you add let bar = String::from("123456");in front of the last
|
Mark-Simulacrum
added
the
C-bug
label
Jul 24, 2017
arielb1
referenced this issue
Oct 24, 2017
Merged
add TerminatorKind::FalseEdges and use it in matches #45384
This comment has been minimized.
This comment has been minimized.
|
cc #27282 -- seems like a duplicate of that |
nikomatsakis
added
the
WG-compiler-nll
label
Jan 11, 2018
nikomatsakis
added this to the
NLL Future Compat Warnings milestone
Jan 11, 2018
nikomatsakis
modified the milestones:
NLL run-pass without ICEs,
NLL soundness violations
Jan 19, 2018
nikomatsakis
referenced this issue
Jan 31, 2018
Closed
Allow *local* mutation and assignments in pattern guards #1006
nikomatsakis
added
the
NLL-sound
label
Mar 14, 2018
matthewjasper
added
NLL-fixed-by-NLL
and removed
NLL-sound
labels
Apr 24, 2018
This comment has been minimized.
This comment has been minimized.
|
Discussed in the weekly NLL triage. |
tmiasko commentedJan 29, 2016
Following compiles, and crashes when trying to print moved from value: