Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3314,13 +3314,22 @@ impl<T, A: Allocator> VecDeque<T, A> {
let (front, back) = self.as_slices();
let cmp_back = back.first().map(|elem| f(elem));

if let Some(Ordering::Equal) = cmp_back {
let result = if let Some(Ordering::Equal) = cmp_back {
Ok(front.len())
} else if let Some(Ordering::Less) = cmp_back {
back.binary_search_by(f).map(|idx| idx + front.len()).map_err(|idx| idx + front.len())
} else {
front.binary_search_by(f)
};

match result {
// SAFETY: `index` points at an element of one of the two slices.
Ok(index) => unsafe { core::hint::assert_unchecked(index < self.len()) },
// SAFETY: An insertion point in either slice is at most one past the deque's end.
Err(index) => unsafe { core::hint::assert_unchecked(index <= self.len()) },
}

result
}

/// Binary searches this `VecDeque` with a key extraction function.
Expand Down
35 changes: 35 additions & 0 deletions tests/codegen-llvm/vec-deque-binary-search-index-no-bound-check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//@ compile-flags: -Copt-level=3
#![crate_type = "lib"]

use std::collections::VecDeque;

unsafe extern "C" {
safe fn vec_deque_binary_search_insertion_point_out_of_bounds();
}

// Make sure no bounds check is emitted when indexing with a successful search result.

// CHECK-LABEL: @vec_deque_binary_search_index_no_bounds_check
#[no_mangle]
pub fn vec_deque_binary_search_index_no_bounds_check(deque: &VecDeque<u8>) -> u8 {
// CHECK-NOT: expect_failed
if let Ok(index) = deque.binary_search_by(|element| element.cmp(&b'\\')) {
deque[index]
} else {
42
}
}

// An unsuccessful search result is a valid insertion point.

// CHECK-LABEL: @vec_deque_binary_search_insertion_point_in_bounds
#[no_mangle]
pub fn vec_deque_binary_search_insertion_point_in_bounds(deque: &VecDeque<u8>) {
// CHECK-NOT: call void @vec_deque_binary_search_insertion_point_out_of_bounds
// CHECK: ret void
if let Err(index) = deque.binary_search_by(|element| element.cmp(&b'\\')) {
if index > deque.len() {
vec_deque_binary_search_insertion_point_out_of_bounds()
}
}
}
Loading