Auto merge of #81732 - m-ou-se:inherit-overflow-checks, r=Mark-Simulacrum

Use `#[rustc_inherit_overflow_checks]` instead of Add::add etc.

See https://github.com/rust-lang/rust/issues/81721
This commit is contained in:
bors 2021-02-22 04:07:05 +00:00
commit e952db8fd0
4 changed files with 65 additions and 38 deletions

View File

@ -1,6 +1,6 @@
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
use crate::ops::{Add, AddAssign, Try};
use crate::ops::Try;
/// An iterator that yields the current count and the element during iteration.
///
@ -39,11 +39,11 @@ where
///
/// Might panic if the index of the element overflows a `usize`.
#[inline]
#[rustc_inherit_overflow_checks]
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
let a = self.iter.next()?;
let i = self.count;
// Possible undefined overflow.
AddAssign::add_assign(&mut self.count, 1);
self.count += 1;
Some((i, a))
}
@ -53,11 +53,11 @@ where
}
#[inline]
#[rustc_inherit_overflow_checks]
fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
let a = self.iter.nth(n)?;
// Possible undefined overflow.
let i = Add::add(self.count, n);
self.count = Add::add(i, 1);
let i = self.count + n;
self.count = i + 1;
Some((i, a))
}
@ -78,10 +78,10 @@ where
count: &'a mut usize,
mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
#[rustc_inherit_overflow_checks]
move |acc, item| {
let acc = fold(acc, (*count, item));
// Possible undefined overflow.
AddAssign::add_assign(count, 1);
*count += 1;
acc
}
}
@ -99,10 +99,10 @@ where
mut count: usize,
mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
) -> impl FnMut(Acc, T) -> Acc {
#[rustc_inherit_overflow_checks]
move |acc, item| {
let acc = fold(acc, (count, item));
// Possible undefined overflow.
AddAssign::add_assign(&mut count, 1);
count += 1;
acc
}
}
@ -110,6 +110,7 @@ where
self.iter.fold(init, enumerate(self.count, fold))
}
#[rustc_inherit_overflow_checks]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
where
Self: TrustedRandomAccess,
@ -117,7 +118,7 @@ where
// SAFETY: the caller must uphold the contract for
// `Iterator::__iterator_get_unchecked`.
let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
(Add::add(self.count, idx), value)
(self.count + idx, value)
}
}

View File

@ -1,7 +1,7 @@
use crate::char;
use crate::convert::TryFrom;
use crate::mem;
use crate::ops::{self, Add, Sub, Try};
use crate::ops::{self, Try};
use super::{FusedIterator, TrustedLen};
@ -201,11 +201,12 @@ macro_rules! step_identical_methods {
#[inline]
#[allow(arithmetic_overflow)]
#[rustc_inherit_overflow_checks]
fn forward(start: Self, n: usize) -> Self {
// In debug builds, trigger a panic on overflow.
// This should optimize completely out in release builds.
if Self::forward_checked(start, n).is_none() {
let _ = Add::add(Self::MAX, 1);
let _ = Self::MAX + 1;
}
// Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`.
start.wrapping_add(n as Self)
@ -213,11 +214,12 @@ macro_rules! step_identical_methods {
#[inline]
#[allow(arithmetic_overflow)]
#[rustc_inherit_overflow_checks]
fn backward(start: Self, n: usize) -> Self {
// In debug builds, trigger a panic on overflow.
// This should optimize completely out in release builds.
if Self::backward_checked(start, n).is_none() {
let _ = Sub::sub(Self::MIN, 1);
let _ = Self::MIN - 1;
}
// Do wrapping math to allow e.g. `Step::backward(127i8, 255)`.
start.wrapping_sub(n as Self)

View File

@ -1,6 +1,5 @@
use crate::iter;
use crate::num::Wrapping;
use crate::ops::{Add, Mul};
/// Trait to represent types that can be created by summing up an iterator.
///
@ -37,34 +36,49 @@ pub trait Product<A = Self>: Sized {
fn product<I: Iterator<Item = A>>(iter: I) -> Self;
}
// N.B., explicitly use Add and Mul here to inherit overflow checks
macro_rules! integer_sum_product {
(@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
#[$attr]
impl Sum for $a {
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold($zero, Add::add)
iter.fold(
$zero,
#[rustc_inherit_overflow_checks]
|a, b| a + b,
)
}
}
#[$attr]
impl Product for $a {
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold($one, Mul::mul)
iter.fold(
$one,
#[rustc_inherit_overflow_checks]
|a, b| a * b,
)
}
}
#[$attr]
impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
iter.fold($zero, Add::add)
iter.fold(
$zero,
#[rustc_inherit_overflow_checks]
|a, b| a + b,
)
}
}
#[$attr]
impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
iter.fold($one, Mul::mul)
iter.fold(
$one,
#[rustc_inherit_overflow_checks]
|a, b| a * b,
)
}
}
)*);
@ -83,28 +97,44 @@ macro_rules! float_sum_product {
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Sum for $a {
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold(0.0, Add::add)
iter.fold(
0.0,
#[rustc_inherit_overflow_checks]
|a, b| a + b,
)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Product for $a {
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold(1.0, Mul::mul)
iter.fold(
1.0,
#[rustc_inherit_overflow_checks]
|a, b| a * b,
)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
iter.fold(0.0, Add::add)
iter.fold(
0.0,
#[rustc_inherit_overflow_checks]
|a, b| a + b,
)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
iter.fold(1.0, Mul::mul)
iter.fold(
1.0,
#[rustc_inherit_overflow_checks]
|a, b| a * b,
)
}
}
)*)

View File

@ -3,7 +3,7 @@
// can't split that into multiple files.
use crate::cmp::{self, Ordering};
use crate::ops::{Add, ControlFlow, Try};
use crate::ops::{ControlFlow, Try};
use super::super::TrustedRandomAccess;
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
@ -242,13 +242,11 @@ pub trait Iterator {
where
Self: Sized,
{
#[inline]
fn add1<T>(count: usize, _: T) -> usize {
// Might overflow.
Add::add(count, 1)
}
self.fold(0, add1)
self.fold(
0,
#[rustc_inherit_overflow_checks]
|count, _| count + 1,
)
}
/// Consumes the iterator, returning the last element.
@ -2475,13 +2473,9 @@ pub trait Iterator {
fn check<T>(
mut predicate: impl FnMut(T) -> bool,
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
// The addition might panic on overflow
#[rustc_inherit_overflow_checks]
move |i, x| {
if predicate(x) {
ControlFlow::Break(i)
} else {
ControlFlow::Continue(Add::add(i, 1))
}
if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i + 1) }
}
}