Rollup merge of #89835 - jkugelman:must-use-expensive-computations, r=joshtriplett

Add #[must_use] to expensive computations

The unifying theme for this commit is weak, admittedly. I put together a list of "expensive" functions when I originally proposed this whole effort, but nobody's cared about that criterion. Still, it's a decent way to bite off a not-too-big chunk of work.

Given the grab bag nature of this commit, the messages I used vary quite a bit. I'm open to wording changes.

For some reason clippy flagged four `BTreeSet` methods but didn't say boo about equivalent ones on `HashSet`. I stared at them for a while but I can't figure out the difference so I added the `HashSet` ones in.

```rust
// Flagged by clippy.
alloc::collections::btree_set::BTreeSet<T>   fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T>;
alloc::collections::btree_set::BTreeSet<T>   fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>) -> SymmetricDifference<'a, T>
alloc::collections::btree_set::BTreeSet<T>   fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> Intersection<'a, T>;
alloc::collections::btree_set::BTreeSet<T>   fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T>;

// Ignored by clippy, but not by me.
std::collections::HashSet<T, S>              fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S>;
std::collections::HashSet<T, S>              fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>) -> SymmetricDifference<'a, T, S>
std::collections::HashSet<T, S>              fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S>;
std::collections::HashSet<T, S>              fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S>;
```

Parent issue: #89692

r? ```@joshtriplett```
This commit is contained in:
Matthias Krüger 2021-10-31 09:20:24 +01:00 committed by GitHub
commit a26b1d2259
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 32 additions and 1 deletions

View File

@ -137,6 +137,8 @@ pub struct Range<'a, T: 'a> {
/// See its documentation for more. /// See its documentation for more.
/// ///
/// [`difference`]: BTreeSet::difference /// [`difference`]: BTreeSet::difference
#[must_use = "this returns the difference as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Difference<'a, T: 'a> { pub struct Difference<'a, T: 'a> {
inner: DifferenceInner<'a, T>, inner: DifferenceInner<'a, T>,
@ -169,6 +171,8 @@ impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
/// [`BTreeSet`]. See its documentation for more. /// [`BTreeSet`]. See its documentation for more.
/// ///
/// [`symmetric_difference`]: BTreeSet::symmetric_difference /// [`symmetric_difference`]: BTreeSet::symmetric_difference
#[must_use = "this returns the difference as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner<Iter<'a, T>>); pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
@ -185,6 +189,8 @@ impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
/// See its documentation for more. /// See its documentation for more.
/// ///
/// [`intersection`]: BTreeSet::intersection /// [`intersection`]: BTreeSet::intersection
#[must_use = "this returns the intersection as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Intersection<'a, T: 'a> { pub struct Intersection<'a, T: 'a> {
inner: IntersectionInner<'a, T>, inner: IntersectionInner<'a, T>,
@ -217,6 +223,8 @@ impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
/// See its documentation for more. /// See its documentation for more.
/// ///
/// [`union`]: BTreeSet::union /// [`union`]: BTreeSet::union
#[must_use = "this returns the union as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Union<'a, T: 'a>(MergeIterInner<Iter<'a, T>>); pub struct Union<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);

View File

@ -552,6 +552,7 @@ impl String {
/// ///
/// assert_eq!("Hello <20>World", output); /// assert_eq!("Hello <20>World", output);
/// ``` /// ```
#[must_use]
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
@ -646,6 +647,7 @@ impl String {
/// String::from_utf16_lossy(v)); /// String::from_utf16_lossy(v));
/// ``` /// ```
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[must_use]
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn from_utf16_lossy(v: &[u16]) -> String { pub fn from_utf16_lossy(v: &[u16]) -> String {

View File

@ -11,6 +11,7 @@ use crate::ops;
impl [u8] { impl [u8] {
/// Checks if all bytes in this slice are within the ASCII range. /// Checks if all bytes in this slice are within the ASCII range.
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[must_use]
#[inline] #[inline]
pub fn is_ascii(&self) -> bool { pub fn is_ascii(&self) -> bool {
is_ascii(self) is_ascii(self)
@ -21,6 +22,7 @@ impl [u8] {
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
/// but without allocating and copying temporaries. /// but without allocating and copying temporaries.
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[must_use]
#[inline] #[inline]
pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))

View File

@ -37,6 +37,7 @@ fn repeat_byte(b: u8) -> usize {
} }
/// Returns the first index matching the byte `x` in `text`. /// Returns the first index matching the byte `x` in `text`.
#[must_use]
#[inline] #[inline]
pub fn memchr(x: u8, text: &[u8]) -> Option<usize> { pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
// Fast path for small slices // Fast path for small slices
@ -91,6 +92,7 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
} }
/// Returns the last index matching the byte `x` in `text`. /// Returns the last index matching the byte `x` in `text`.
#[must_use]
pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> { pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
// Scan for a single byte value by reading two `usize` words at a time. // Scan for a single byte value by reading two `usize` words at a time.
// //

View File

@ -27,6 +27,7 @@ use super::{IsAsciiWhitespace, IsNotEmpty, IsWhitespace};
/// [`char`]: prim@char /// [`char`]: prim@char
/// [`chars`]: str::chars /// [`chars`]: str::chars
#[derive(Clone)] #[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Chars<'a> { pub struct Chars<'a> {
pub(super) iter: slice::Iter<'a, u8>, pub(super) iter: slice::Iter<'a, u8>,
@ -125,6 +126,7 @@ impl<'a> Chars<'a> {
/// [`char`]: prim@char /// [`char`]: prim@char
/// [`char_indices`]: str::char_indices /// [`char_indices`]: str::char_indices
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct CharIndices<'a> { pub struct CharIndices<'a> {
pub(super) front_offset: usize, pub(super) front_offset: usize,
@ -1089,6 +1091,7 @@ generate_pattern_iterators! {
/// ///
/// [`lines`]: str::lines /// [`lines`]: str::lines
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Lines<'a>(pub(super) Map<SplitTerminator<'a, char>, LinesAnyMap>); pub struct Lines<'a>(pub(super) Map<SplitTerminator<'a, char>, LinesAnyMap>);
@ -1128,6 +1131,7 @@ impl FusedIterator for Lines<'_> {}
/// [`lines_any`]: str::lines_any /// [`lines_any`]: str::lines_any
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")] #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[allow(deprecated)] #[allow(deprecated)]
pub struct LinesAny<'a>(pub(super) Lines<'a>); pub struct LinesAny<'a>(pub(super) Lines<'a>);

View File

@ -29,6 +29,7 @@ impl Utf8Lossy {
} }
/// Iterator over lossy UTF-8 string /// Iterator over lossy UTF-8 string
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[unstable(feature = "str_internals", issue = "none")] #[unstable(feature = "str_internals", issue = "none")]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Utf8LossyChunksIter<'a> { pub struct Utf8LossyChunksIter<'a> {

View File

@ -2255,6 +2255,7 @@ impl str {
/// assert!(!non_ascii.is_ascii()); /// assert!(!non_ascii.is_ascii());
/// ``` /// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[must_use]
#[inline] #[inline]
pub fn is_ascii(&self) -> bool { pub fn is_ascii(&self) -> bool {
// We can treat each byte as character here: all multibyte characters // We can treat each byte as character here: all multibyte characters
@ -2276,6 +2277,7 @@ impl str {
/// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
/// ``` /// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[must_use]
#[inline] #[inline]
pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) self.as_bytes().eq_ignore_ascii_case(other.as_bytes())

View File

@ -115,7 +115,7 @@ fn test_eq_ignore_ascii_case() {
#[test] #[test]
fn inference_works() { fn inference_works() {
let x = "a".to_string(); let x = "a".to_string();
x.eq_ignore_ascii_case("A"); let _ = x.eq_ignore_ascii_case("A");
} }
// Shorthands used by the is_ascii_* tests. // Shorthands used by the is_ascii_* tests.

View File

@ -1320,6 +1320,8 @@ where
/// ///
/// let mut intersection = a.intersection(&b); /// let mut intersection = a.intersection(&b);
/// ``` /// ```
#[must_use = "this returns the intersection as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Intersection<'a, T: 'a, S: 'a> { pub struct Intersection<'a, T: 'a, S: 'a> {
// iterator of the first set // iterator of the first set
@ -1345,6 +1347,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> {
/// ///
/// let mut difference = a.difference(&b); /// let mut difference = a.difference(&b);
/// ``` /// ```
#[must_use = "this returns the difference as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Difference<'a, T: 'a, S: 'a> { pub struct Difference<'a, T: 'a, S: 'a> {
// iterator of the first set // iterator of the first set
@ -1370,6 +1374,8 @@ pub struct Difference<'a, T: 'a, S: 'a> {
/// ///
/// let mut intersection = a.symmetric_difference(&b); /// let mut intersection = a.symmetric_difference(&b);
/// ``` /// ```
#[must_use = "this returns the difference as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct SymmetricDifference<'a, T: 'a, S: 'a> { pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>, iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
@ -1392,6 +1398,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
/// ///
/// let mut union_iter = a.union(&b); /// let mut union_iter = a.union(&b);
/// ``` /// ```
#[must_use = "this returns the union as an iterator, \
without modifying either input set"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Union<'a, T: 'a, S: 'a> { pub struct Union<'a, T: 'a, S: 'a> {
iter: Chain<Iter<'a, T>, Difference<'a, T, S>>, iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,

View File

@ -829,6 +829,7 @@ impl OsStr {
/// assert!(!non_ascii.is_ascii()); /// assert!(!non_ascii.is_ascii());
/// ``` /// ```
#[stable(feature = "osstring_ascii", since = "1.53.0")] #[stable(feature = "osstring_ascii", since = "1.53.0")]
#[must_use]
#[inline] #[inline]
pub fn is_ascii(&self) -> bool { pub fn is_ascii(&self) -> bool {
self.inner.is_ascii() self.inner.is_ascii()

View File

@ -487,6 +487,7 @@ impl Stdin {
/// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap())); /// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap()));
/// } /// }
/// ``` /// ```
#[must_use = "`self` will be dropped if the result is not used"]
#[unstable(feature = "stdin_forwarders", issue = "87096")] #[unstable(feature = "stdin_forwarders", issue = "87096")]
pub fn split(self, byte: u8) -> Split<StdinLock<'static>> { pub fn split(self, byte: u8) -> Split<StdinLock<'static>> {
self.into_locked().split(byte) self.into_locked().split(byte)