-
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
VecDeque is_empty and get(0) together generate unreachable panic. #80836
Comments
Does the compiler have any support for that kind of optimization? I don't think it has special knowledge of |
This is the generated MIR (in release mode) by the way: // WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
fn front(_1: &mut VecDeque<usize>) -> () {
debug v => _1; // in scope 0 at src/lib.rs:3:14: 3:15
let mut _0: (); // return place in scope 0 at src/lib.rs:3:39: 3:39
let mut _2: bool; // in scope 0 at src/lib.rs:4:8: 4:21
let mut _3: bool; // in scope 0 at src/lib.rs:4:9: 4:21
let mut _4: &std::collections::VecDeque<usize>; // in scope 0 at src/lib.rs:4:9: 4:10
let _5: &usize; // in scope 0 at src/lib.rs:5:9: 5:31
let mut _6: std::option::Option<&usize>; // in scope 0 at src/lib.rs:5:9: 5:17
let mut _7: &std::collections::VecDeque<usize>; // in scope 0 at src/lib.rs:5:9: 5:10
let mut _8: &str; // in scope 0 at src/lib.rs:5:25: 5:30
let _9: &str; // in scope 0 at src/lib.rs:5:25: 5:30
bb0: {
StorageLive(_2); // scope 0 at src/lib.rs:4:8: 4:21
StorageLive(_3); // scope 0 at src/lib.rs:4:9: 4:21
StorageLive(_4); // scope 0 at src/lib.rs:4:9: 4:10
_4 = &(*_1); // scope 0 at src/lib.rs:4:9: 4:10
_3 = VecDeque::<usize>::is_empty(move _4) -> bb1; // scope 0 at src/lib.rs:4:9: 4:21
// mir::Constant
// + span: src/lib.rs:4:11: 4:19
// + literal: Const { ty: for<'r> fn(&'r std::collections::VecDeque<usize>) -> bool {std::collections::VecDeque::<usize>::is_empty}, val: Value(Scalar(<ZST>)) }
}
bb1: {
StorageDead(_4); // scope 0 at src/lib.rs:4:20: 4:21
_2 = Not(move _3); // scope 0 at src/lib.rs:4:8: 4:21
StorageDead(_3); // scope 0 at src/lib.rs:4:20: 4:21
switchInt(_2) -> [false: bb2, otherwise: bb3]; // scope 0 at src/lib.rs:4:5: 6:6
}
bb2: {
_0 = const (); // scope 0 at src/lib.rs:4:5: 6:6
goto -> bb6; // scope 0 at src/lib.rs:4:5: 6:6
}
bb3: {
StorageLive(_5); // scope 0 at src/lib.rs:5:9: 5:31
StorageLive(_6); // scope 0 at src/lib.rs:5:9: 5:17
StorageLive(_7); // scope 0 at src/lib.rs:5:9: 5:10
_7 = &(*_1); // scope 0 at src/lib.rs:5:9: 5:10
_6 = VecDeque::<usize>::get(move _7, const 0_usize) -> bb4; // scope 0 at src/lib.rs:5:9: 5:17
// mir::Constant
// + span: src/lib.rs:5:11: 5:14
// + literal: Const { ty: for<'r> fn(&'r std::collections::VecDeque<usize>, usize) -> std::option::Option<&'r usize> {std::collections::VecDeque::<usize>::get}, val: Value(Scalar(<ZST>)) }
}
bb4: {
StorageDead(_7); // scope 0 at src/lib.rs:5:16: 5:17
StorageLive(_8); // scope 0 at src/lib.rs:5:25: 5:30
StorageLive(_9); // scope 0 at src/lib.rs:5:25: 5:30
_9 = const "foo"; // scope 0 at src/lib.rs:5:25: 5:30
// ty::Const
// + ty: &str
// + val: Value(Slice { data: Allocation { bytes: [102, 111, 111], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [7], len: Size { raw: 3 } }, size: Size { raw: 3 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 3 })
// mir::Constant
// + span: src/lib.rs:5:25: 5:30
// + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [102, 111, 111], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [7], len: Size { raw: 3 } }, size: Size { raw: 3 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 3 }) }
_8 = _9; // scope 0 at src/lib.rs:5:25: 5:30
_5 = Option::<&usize>::expect(move _6, move _8) -> bb5; // scope 0 at src/lib.rs:5:9: 5:31
// mir::Constant
// + span: src/lib.rs:5:18: 5:24
// + literal: Const { ty: for<'r> fn(std::option::Option<&usize>, &'r str) -> &usize {std::option::Option::<&usize>::expect}, val: Value(Scalar(<ZST>)) }
}
bb5: {
StorageDead(_8); // scope 0 at src/lib.rs:5:30: 5:31
StorageDead(_6); // scope 0 at src/lib.rs:5:30: 5:31
StorageDead(_9); // scope 0 at src/lib.rs:5:31: 5:32
StorageDead(_5); // scope 0 at src/lib.rs:5:31: 5:32
_0 = const (); // scope 0 at src/lib.rs:4:22: 6:6
goto -> bb6; // scope 0 at src/lib.rs:4:5: 6:6
}
bb6: {
StorageDead(_2); // scope 0 at src/lib.rs:7:1: 7:2
return; // scope 0 at src/lib.rs:7:2: 7:2
}
} |
I don't think special knowledge is necessary. There are some assumptions that are missing, which make the Also, the MIR isn't particularly helpful here as calls aren't inlined, so we just see |
The main problem looks something like this:
For whatever reason, even if the compiler knows The main issue seems to be that the binary and loses information. See here: https://rust.godbolt.org/z/77MaGW - if you delete the |
That would be nice! :D |
There are two issues here. First is convoluted implementation of VecDeque itself where implementations of But even if Some(&*buf.ptr.as_ptr()).unwrap() to actually check for |
Doesn't seem like the LLVM update fixed it because the unreachable panic is still present on nightly. |
Switched to nightly and it now returns:
So it seems fixed. Please reopen or file a new issue if there's still an issue. |
Does this need a test to guard against regression? |
I don't think |
Marking this as E-medium. It should not be too hard but you will need to know (or learn!) about codegen tests. |
…rk-Simulacrum Add codegen test to guard against VecDeque optimization regression Very small PR that adds a codegen test to guard against regression for the `VecDeque` optimization addressed in rust-lang#80836. Ensures that Rustc optimizes away the panic when unwrapping the result of `.get(0)` because of the `!is_empty()` condition.
https://rust.godbolt.org/z/oe4q69
For some reason, the knowledge that a
VecDeque
is empty, is not preserved when callingget(0)
(or evenfront
) and the compiler generates panics which are unreachable.The text was updated successfully, but these errors were encountered: