mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #83726 - the8472:large-trustedlen-fail-fast, r=kennytm
panic early when `TrustedLen` indicates a `length > usize::MAX` Changes `TrustedLen` specializations to immediately panic when `size_hint().1 == None`. As far as I can tell this is ~not a change~ a minimal change in observable behavior for anything except ZSTs because the fallback path would go through `extend_desugared()` which tries to `reserve(lower_bound)` which already is `usize::MAX` and that would also lead to a panic. Before it might have popped somewhere between zero and a few elements from the iterator before panicking while it now panics immediately. Overall this should reduce codegen by eliminating the fallback paths. While looking into the `with_capacity()` behavior I also noticed that its documentation didn't have a *Panics* section, so I added that.
This commit is contained in:
commit
803ddb8359
@ -1848,8 +1848,11 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
|
||||
Rc::from_iter_exact(self, low)
|
||||
}
|
||||
} else {
|
||||
// Fall back to normal implementation.
|
||||
self.collect::<Vec<T>>().into()
|
||||
// TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
|
||||
// length exceeding `usize::MAX`.
|
||||
// The default implementation would collect into a vec which would panic.
|
||||
// Thus we panic here immediately without invoking `Vec` code.
|
||||
panic!("capacity overflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2481,8 +2481,11 @@ impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I {
|
||||
Arc::from_iter_exact(self, low)
|
||||
}
|
||||
} else {
|
||||
// Fall back to normal implementation.
|
||||
self.collect::<Vec<T>>().into()
|
||||
// TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
|
||||
// length exceeding `usize::MAX`.
|
||||
// The default implementation would collect into a vec which would panic.
|
||||
// Thus we panic here immediately without invoking `Vec` code.
|
||||
panic!("capacity overflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -410,6 +410,10 @@ impl<T> Vec<T> {
|
||||
///
|
||||
/// [Capacity and reallocation]: #capacity-and-reallocation
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the new capacity exceeds `isize::MAX` bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -541,6 +545,10 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
///
|
||||
/// [Capacity and reallocation]: #capacity-and-reallocation
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the new capacity exceeds `isize::MAX` bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -47,7 +47,12 @@ where
|
||||
});
|
||||
}
|
||||
} else {
|
||||
self.extend_desugared(iterator)
|
||||
// Per TrustedLen contract a `None` upper bound means that the iterator length
|
||||
// truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway.
|
||||
// Since the other branch already panics eagerly (via `reserve()`) we do the same here.
|
||||
// This avoids additional codegen for a fallback code path which would eventually
|
||||
// panic anyway.
|
||||
panic!("capacity overflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,10 +46,13 @@ where
|
||||
fn from_iter(iterator: I) -> Self {
|
||||
let mut vector = match iterator.size_hint() {
|
||||
(_, Some(upper)) => Vec::with_capacity(upper),
|
||||
_ => Vec::new(),
|
||||
// TrustedLen contract guarantees that `size_hint() == (_, None)` means that there
|
||||
// are more than `usize::MAX` elements.
|
||||
// Since the previous branch would eagerly panic if the capacity is too large
|
||||
// (via `with_capacity`) we do the same here.
|
||||
_ => panic!("capacity overflow"),
|
||||
};
|
||||
// must delegate to spec_extend() since extend() itself delegates
|
||||
// to spec_from for empty Vecs
|
||||
// reuse extend specialization for TrustedLen
|
||||
vector.spec_extend(iterator);
|
||||
vector
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user