You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The NLL RFC specifies false edges on infinite loops, so that we get errors in some cases. This is a somewhat disputed clause (see nikomatsakis/nll-rfc#35) that we may change, but it makes sense for now. I'm filing this so we don't forget about it.
So @mikhail-m1 added the notion of "false edges" in #45384. This seems to be roughly what is needed here. We would want to edit the code that generates a loop construct:
This might take some time, I getting core dumped error, I need to learn about what's happening before moving things here and there. If this is required to be fixed urgently, I am good with someone else fixing it.
So playing with implementing this I've run in to a stumbling block. It seems like TerminatorKind::FalseEdges is mostly intended for use where control flow could sort-of follow the false edge in "normal" execution; the motivating example being things being moved in match arm guards. However in the situation mentioned here, control flow truly follows the false edge in "exceptional" circumstances (panics). The trouble is that there are a number of analysis passes that don't handle this and I'm not sure how to get that knowledge in to them. The first one I've run in to is MIR typeck:
fnoh_no1() -> i32{loop{return1;}// we abort here since the fake edge means MIR typeck tries to assert that () == i32// even though the only way we can get here is if we're unwinding and at that point the// return value doesn't matter}
Ah, very good point! You are correct that this control flow is supposed to be like a "false unwind".
My instructions were wrong in this respect. We want the false edge not to "break out" but rather to go to an unwinding target. Basically, where we would unwind to, if we were unwinding. The method to get such a block is diverge_cleanup, iirc:
/// Creates a path that performs all required cleanup for unwinding.
///
/// This path terminates in Resume. Returns the start of the path.
/// See module comment for more details. None indicates there’s no
/// cleanup to do at this point.
pubfndiverge_cleanup(&mutself) -> BasicBlock{
self.diverge_cleanup_gen(false)
}
I'm not sure whether we will have to further modify FalseEdges to distinguish between a "false unwinding" edge and a "false normal" edge. If so, we can probably just add a boolean flag or something like that.
Activity
nikomatsakis commentedon Jan 17, 2018
So @mikhail-m1 added the notion of "false edges" in #45384. This seems to be roughly what is needed here. We would want to edit the code that generates a
loopconstruct:rust/src/librustc_mir/build/expr/into.rs
Lines 149 to 204 in 3e49ada
and modify the graph in the case where condition is
None:rust/src/librustc_mir/build/expr/into.rs
Line 191 in 3e49ada
so that we create a FalseEdges that "breaks out".
nikomatsakis commentedon Jan 17, 2018
Added some mentoring instructions to this NLL issue. Can elaborate as needed!
cc nll folks:
@davidtwco
@chrisvittal
@pnkfelix
@spastorino
@Nashenas88
@gaurikholkar
@qmx
@Pulkit07
@ritiek
Pulkit07 commentedon Jan 17, 2018
I am trying to fix this one. I have already a kind of patch ready, need to dump MIR and see if it's doing the right thing.
nikomatsakis commentedon Jan 18, 2018
@Pulkit07 nice :)
Pulkit07 commentedon Jan 18, 2018
This might take some time, I getting
core dumpederror, I need to learn about what's happening before moving things here and there. If this is required to be fixed urgently, I am good with someone else fixing it.nikomatsakis commentedon Jan 18, 2018
@Pulkit07 woah, core dumped?! When do you get the error, when bootstrapping?
Pulkit07 commentedon Jan 19, 2018
@nikomatsakis I am getting this error when running tests like src/test/run-pass/auto-loop.rs, src/test/run-pass/break.rs and many others.
nikomatsakis commentedon Jan 19, 2018
@Pulkit07 even if you don't have time to continue working, it'd be helpful if you could post the diff somewhere of how far you got
nikomatsakis commentedon Jan 19, 2018
From gitter, here is the diff https://bpaste.net/show/ac4eab0ead8e
sapphire-arches commentedon Jan 23, 2018
So playing with implementing this I've run in to a stumbling block. It seems like
TerminatorKind::FalseEdgesis mostly intended for use where control flow could sort-of follow the false edge in "normal" execution; the motivating example being things being moved in match arm guards. However in the situation mentioned here, control flow truly follows the false edge in "exceptional" circumstances (panics). The trouble is that there are a number of analysis passes that don't handle this and I'm not sure how to get that knowledge in to them. The first one I've run in to is MIR typeck:nikomatsakis commentedon Jan 24, 2018
@bobtwinkles
Ah, very good point! You are correct that this control flow is supposed to be like a "false unwind".
My instructions were wrong in this respect. We want the false edge not to "break out" but rather to go to an unwinding target. Basically, where we would unwind to, if we were unwinding. The method to get such a block is
diverge_cleanup, iirc:rust/src/librustc_mir/build/scope.rs
Lines 715 to 722 in 3e49ada
I'm not sure whether we will have to further modify
FalseEdgesto distinguish between a "false unwinding" edge and a "false normal" edge. If so, we can probably just add a boolean flag or something like that.nikomatsakis commentedon Jan 26, 2018
Here is a test case that @bobtwinkles and I discussed on IRC:
https://play.rust-lang.org/?gist=f9b57ba12faa3e9bc8e4a4d523d58736&version=nightly
Right now, it ICEs, but it also ought to be reporting an error if this is all working correctly.
mir: Add false edge cleanup out of infinite loops
Auto merge of #47802 - bobtwinkles:loop_false_edge, r=nikomatsakis
Rollup merge of rust-lang#81387 - c410-f3r:tests-tests-tests, r=petro…
Rollup merge of rust-lang#81387 - c410-f3r:tests-tests-tests, r=petro…