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 upVariables moved from in match guards are still accessible in other match arms. #29723
Comments
This comment has been minimized.
This comment has been minimized.
|
Possibly aided by #3478? |
eddyb
changed the title
Moving values in match guards can lead to runtime segfaults
Variables moved from in match guards are still accessible in other match arms.
Nov 9, 2015
eddyb
added
the
A-borrow-checker
label
Nov 9, 2015
This comment has been minimized.
This comment has been minimized.
fn main() {
let s = String::new();
let _s = match 0 {
0 if { drop(s); false } => String::from("oops"),
_ => {
// This should trigger an error,
// s could have been moved from.
s
}
};
} |
This comment has been minimized.
This comment has been minimized.
|
This would be solved by the MIR, right? |
This comment has been minimized.
This comment has been minimized.
LLBlumire
commented
Nov 9, 2015
|
Bringing mine and @eddyb 's IRC conversation into here for readability. The issue is that the path on the left in the image above does not chain into the path on the right, meaning that This seems to be a configuration issue in https://github.com/rust-lang/rust/blob/master/src/librustc/middle/cfg/construct.rs#L429-L529 |
brson
added
I-nominated
T-compiler
labels
Nov 9, 2015
This comment has been minimized.
This comment has been minimized.
|
Wait can you move in guards? |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 you shouldn't be able to |
This comment has been minimized.
This comment has been minimized.
|
Hmm, looks like I missed this case when I fixed a very similar issue (moving in multiple guard expressions). The issue is that the way the final guard is handled means that it acts as if it can't fail. Wiring up the contents of @Manishearth I tried disallowing it, but there's some code around that moves in guards. Its also a breaking change. |
This comment has been minimized.
This comment has been minimized.
|
Ok, in trying to fix this I ran into an issue that is probably why I didn't handle this case last time. Borrows due to by-ref bindings in matches are scoped the match expression itself, meaning that something like: match foo_opt {
Some(ref foo) if cond => { ... }
None => { foo_opt.val = bar; }
}will complain that you can't assign to |
bstrie
added
the
I-unsound 💥
label
Nov 10, 2015
This comment has been minimized.
This comment has been minimized.
|
@eddyb How did you get rustc to spit out the CFG like that? |
This comment has been minimized.
This comment has been minimized.
|
@bstrie |
This comment has been minimized.
This comment has been minimized.
|
Oh, it's |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Key question is whether it's worth trying to fix this now, or just accelerate efforts to port borrowck to MIR. There are already a number of these sorts of issues that would be fixed by such a thing. @Aatch what efforts did you make to fix this? |
This comment has been minimized.
This comment has been minimized.
|
triage: P-high High because soundness but maybe we should downgrade to medium or otherwise try to solve via MIR. |
rust-highfive
added
P-high
and removed
I-nominated
labels
Nov 12, 2015
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis I tried to change the CFG to represent the control flow more accurately but ran into the issue I described above. I think there needs to be a change to the regions around match arms, but I'm less familiar with the code there and not sure what to change or how. |
This comment has been minimized.
This comment has been minimized.
|
triage: P-medium Since we're basically waiting for MIR to fix this, it's not really P-high |
rust-highfive
added
P-medium
and removed
P-high
labels
Nov 19, 2015
pnkfelix
added
the
A-mir
label
Nov 19, 2015
This comment has been minimized.
This comment has been minimized.
|
(tagging with |
brson
added
the
E-hard
label
Aug 4, 2016
nikomatsakis
removed
the
A-mir
label
Aug 4, 2016
This comment has been minimized.
This comment has been minimized.
|
This is still relevant on the latest nightly. |
This comment has been minimized.
This comment has been minimized.
sp-1234
commented
Oct 3, 2017
|
Is there an ETA for this or something? |
This comment has been minimized.
This comment has been minimized.
|
@sp-1234 Regarding an ETA, the plan seems to be that this will be fixed by the act of migrating the borrow-checker to later in the pipeline of compiler passes. This has been in the works for quite a while now and should be ready by the end of this year. This will also fix several other soundness bugs of the same nature. |
This comment has been minimized.
This comment has been minimized.
|
@bstrie "later"? Are you referring to MIR borrowck? That has nothing to do with "earlier" or "later" (in fact, at least until recently, borrowck has always ran second-to-last, just before lints, which probably still are the last thing in the analysis passes, before translation), but rather the underlying abstraction on which the the checking is performed - with MIR, complex language-level constructs do not require as complex of handling, sometimes even being subsumed by the generality of MIR dataflow. |
arielb1
referenced this issue
Oct 11, 2017
Closed
MIR: permit "false edges", that are only used in the analysis #45184
This comment has been minimized.
This comment has been minimized.
|
Turns out we need either NLL (the conditionally-canceled borrow part) or having differently-typed guard binding and body binding variables to make this work: use std::cell::RefCell;
fn assign<'a, 'b>(x: &RefCell<Option<&'a &'b mut u32>>, y: &'a &'b mut u32) {
*x.borrow_mut() = Some(y);
}
fn main() {
let (mut t, mut ten);
ten = 10;
t = Some(&mut ten);
unsound(&mut t);
}
fn unsound<'a>(opt: &'a mut Option<&'a mut u32>) -> Option<&'a mut u32> {
let store: RefCell<Option<&&mut u32>> = RefCell::new(None);
match *opt {
#[cfg(segfault)]
Some(ref mut x) if {
// this (making `x` escape from the arm) should be disallowed
// - `x` shouldn't be `&'a mut &'a mut u32` here
assign(&store, x);
false
} => {
None
}
#[cfg(not(segfault))]
Some(ref mut x) if { false } => {
// but just using `x` should be fine: `x` has the type `&'a mut &'a mut u32` here
Some(x)
}
ref mut x => {
*x = None;
println!("{:?}", store.borrow());
None
}
}
} |
arielb1
referenced this issue
Oct 31, 2017
Merged
add TerminatorKind::FalseEdges and use it in matches #45384
This comment has been minimized.
This comment has been minimized.
|
The current status of MIR-borrowck indicates that we can address the first example and the second example. We also correctly reject the My inclination is to land regression tests, alongside |
This comment has been minimized.
This comment has been minimized.
|
FWIW, testing with ariel's example, NLL + MIR borrowck seems to accept |
This comment has been minimized.
This comment has been minimized.
|
I'm increasing priority on this because we should make sure we address it and other related issues as part of migration to NLL. |
pnkfelix
added
P-high
and removed
P-medium
labels
Jan 9, 2018
This comment has been minimized.
This comment has been minimized.
|
This is fixed in MIR borrowck: https://play.rust-lang.org/?gist=3e78648bb9001bd5a96f59d09457f13b&version=nightly |
nikomatsakis
added
the
WG-compiler-nll
label
Jan 11, 2018
nikomatsakis
added this to the
NLL Future Compat Warnings milestone
Jan 11, 2018
nikomatsakis
referenced this issue
Jan 18, 2018
Open
tracking issue for bugs fixed by the MIR borrow checker or NLL #47366
This comment has been minimized.
This comment has been minimized.
|
Added to #47366 -- this is basically E-needstest now |
nikomatsakis
added
E-needstest
and removed
E-hard
labels
Jan 18, 2018
This comment has been minimized.
This comment has been minimized.
|
triage: P-medium |
rust-highfive
added
P-medium
and removed
P-high
labels
Jan 18, 2018
Manishearth
added a commit
to Manishearth/rust
that referenced
this issue
Jan 18, 2018
This comment has been minimized.
This comment has been minimized.
nikomatsakis
removed
the
WG-compiler-nll
label
Jan 18, 2018
nikomatsakis
removed this from the
NLL run-pass without ICEs milestone
Jan 19, 2018
kennytm
added a commit
to kennytm/rust
that referenced
this issue
Jan 23, 2018
bors
closed this
in
101f1e1
Jan 23, 2018
This comment has been minimized.
This comment has been minimized.
|
Awesome! Thanks to everyone who played a part in resolving this |

Toby-S commentedNov 9, 2015
The following code segfaults at runtime on stable, beta, and nightly: