-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
'a: while break 'a{} results in illigal instruction #50856
Comments
Update: fn main() {
'a: while {break 'a; true} { }
1;
} after some more trying, it can be shortened to this (and works for functions other than in main, as shown here: https://play.rust-lang.org/?gist=79ea8fe2b5a1b96ba49089e1b4df1254&version=nightly&mode=debug) : fn main() {
'a: while break 'a{};
} adding a |
Checking the last example with godbolt,
|
Err the last example is even featured in E0590 (introduced in #39864), but why this seems not tested at all 😒. Edit: It generates an // WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
fn main() -> (){
let mut _0: (); // return place
bb0: {
unreachable; // bb0[0]: scope 0 at src/main.rs:1:11: 3:2
}
} The initial MIR already contains an unreachable.// MIR for `main`
// source = MirSource { def_id: DefId(0/0:3 ~ 3[317d]::main[0]), promoted: None }
// pass_name = mir_map
// disambiguator = 0
fn main() -> (){
let mut _0: (); // return place
let mut _1: !;
let mut _2: ();
let mut _3: bool;
let mut _4: !;
let mut _5: ();
bb0: {
goto -> bb1; // bb0[0]: scope 0 at 3.rs:2:5: 2:25
}
bb1: {
StorageLive(_3); // bb1[0]: scope 0 at 3.rs:2:15: 2:23
_2 = (); // bb1[1]: scope 0 at 3.rs:2:15: 2:23
goto -> bb4; // bb1[2]: scope 0 at 3.rs:2:15: 2:23
}
bb2: {
_2 = (); // bb2[0]: scope 0 at 3.rs:2:5: 2:25
StorageDead(_3); // bb2[1]: scope 0 at 3.rs:2:24: 2:25
unreachable; // bb2[2]: scope 0 at 3.rs:1:11: 3:2
}
bb3: { // cleanup
resume; // bb3[0]: scope 0 at 3.rs:1:1: 3:2
}
bb4: {
goto -> bb5; // bb4[0]: scope 0 at 3.rs:2:15: 2:23
}
bb5: {
goto -> bb6; // bb5[0]: scope 0 at 3.rs:2:15: 2:23
}
bb6: {
goto -> bb2; // bb6[0]: scope 0 at 3.rs:2:15: 2:23
}
bb7: {
_4 = (); // bb7[0]: scope 0 at 3.rs:2:15: 2:23
unreachable; // bb7[1]: scope 0 at 3.rs:2:15: 2:23
}
bb8: {
StorageDead(_4); // bb8[0]: scope 0 at 3.rs:2:22: 2:23
switchInt(move _3) -> [false: bb2, otherwise: bb9]; // bb8[1]: scope 0 at 3.rs:2:5: 2:25
}
bb9: {
_5 = (); // bb9[0]: scope 0 at 3.rs:2:23: 2:25
goto -> bb1; // bb9[1]: scope 0 at 3.rs:2:5: 2:25
}
bb10: {
StorageDead(_1); // bb10[0]: scope 0 at 3.rs:3:1: 3:2
goto -> bb11; // bb10[1]: scope 0 at 3.rs:3:2: 3:2
}
bb11: {
return; // bb11[0]: scope 0 at 3.rs:3:2: 3:2
}
} -Zunpretty=hir,typed#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
fn main() ({ ('a: while ((break 'a as !)) { } as ()); } as !) |
It's because in the example that is tested, there's no semicolon: fn main() {
'foo: while break 'foo {} // ok
} fn main() {
'foo: while break 'foo {}; // uh-oh
} Why that makes a difference, I haven't determined yet. |
The problem is, for some reason, the type checker inferred // compile-pass, but shouldn't.
#![feature(never_type)]
fn main() {
let _: ! = { 'a: while break 'a {}; };
} However, without the |
Maybe slightly off-topic, but why are references to the label even allowed in the condition, rather than solely the body? You don't achieve extra expressiveness, as it's equivalent to returning false in the condition, and it makes things more complicated. |
having code like this results in an ICE: const ARR: [(); 0] = [ 'a: while break 'a {}; 0];
fn main() {
}
https://play.rust-lang.org/?gist=56a8ce6081021416d64f4a056aeae8ca&version=stable&mode=debug |
Because it is consistent with the desugaring of the while loop to a 'a: loop {
if { break 'a } { break 'a }
} which is a valid and fairly sensible code. |
I think the bug in in the type-checker then: it should not be giving |
Marking as P-medium: technically a regression, but a very old one, and kind of a corner case. Still, I'll try to leave some notes on how to fix. |
@nikomatsakis: yeah, I can have a look into this. Might be a little delayed, but definitely within the next couple of weeks. |
…omatsakis Fix behaviour of divergence in while loop conditions This fixes `'a: while break 'a {};` being treated as diverging, by tracking break expressions in the same way as in `loop` expressions. Fixes rust-lang#50856. r? @nikomatsakis
Having the following main function results in an illigal instruction on stable, beta and nighlty.
It should be noted that when
n
is not used after the loop, the illigal instruction does not occurhttps://play.rust-lang.org/?gist=96a11fd41327de4bf4e2c371dd7c1660&version=stable&mode=debug
Interestingly putting the same while-loop in a function works fine:
https://play.rust-lang.org/?gist=ed60d2118b970be39e09bc8653a25345&version=stable&mode=debug
The text was updated successfully, but these errors were encountered: