1
Fork 0

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

This commit is contained in:
Mara Bos 2021-02-04 00:20:08 +01:00
parent 07194ffcd2
commit 053769dd53
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::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; 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. /// 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`. /// Might panic if the index of the element overflows a `usize`.
#[inline] #[inline]
#[rustc_inherit_overflow_checks]
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> { fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
let a = self.iter.next()?; let a = self.iter.next()?;
let i = self.count; let i = self.count;
// Possible undefined overflow. self.count += 1;
AddAssign::add_assign(&mut self.count, 1);
Some((i, a)) Some((i, a))
} }
@ -53,11 +53,11 @@ where
} }
#[inline] #[inline]
#[rustc_inherit_overflow_checks]
fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> { fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
let a = self.iter.nth(n)?; let a = self.iter.nth(n)?;
// Possible undefined overflow. let i = self.count + n;
let i = Add::add(self.count, n); self.count = i + 1;
self.count = Add::add(i, 1);
Some((i, a)) Some((i, a))
} }
@ -78,10 +78,10 @@ where
count: &'a mut usize, count: &'a mut usize,
mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a, mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a { ) -> impl FnMut(Acc, T) -> R + 'a {
#[rustc_inherit_overflow_checks]
move |acc, item| { move |acc, item| {
let acc = fold(acc, (*count, item)); let acc = fold(acc, (*count, item));
// Possible undefined overflow. *count += 1;
AddAssign::add_assign(count, 1);
acc acc
} }
} }
@ -99,10 +99,10 @@ where
mut count: usize, mut count: usize,
mut fold: impl FnMut(Acc, (usize, T)) -> Acc, mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
) -> impl FnMut(Acc, T) -> Acc { ) -> impl FnMut(Acc, T) -> Acc {
#[rustc_inherit_overflow_checks]
move |acc, item| { move |acc, item| {
let acc = fold(acc, (count, item)); let acc = fold(acc, (count, item));
// Possible undefined overflow. count += 1;
AddAssign::add_assign(&mut count, 1);
acc acc
} }
} }
@ -110,6 +110,7 @@ where
self.iter.fold(init, enumerate(self.count, fold)) 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 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
where where
Self: TrustedRandomAccess, Self: TrustedRandomAccess,
@ -117,7 +118,7 @@ where
// SAFETY: the caller must uphold the contract for // SAFETY: the caller must uphold the contract for
// `Iterator::__iterator_get_unchecked`. // `Iterator::__iterator_get_unchecked`.
let value = unsafe { try_get_unchecked(&mut self.iter, idx) }; 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::char;
use crate::convert::TryFrom; use crate::convert::TryFrom;
use crate::mem; use crate::mem;
use crate::ops::{self, Add, Sub, Try}; use crate::ops::{self, Try};
use super::{FusedIterator, TrustedLen}; use super::{FusedIterator, TrustedLen};
@ -201,11 +201,12 @@ macro_rules! step_identical_methods {
#[inline] #[inline]
#[allow(arithmetic_overflow)] #[allow(arithmetic_overflow)]
#[rustc_inherit_overflow_checks]
fn forward(start: Self, n: usize) -> Self { fn forward(start: Self, n: usize) -> Self {
// In debug builds, trigger a panic on overflow. // In debug builds, trigger a panic on overflow.
// This should optimize completely out in release builds. // This should optimize completely out in release builds.
if Self::forward_checked(start, n).is_none() { 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)`. // Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`.
start.wrapping_add(n as Self) start.wrapping_add(n as Self)
@ -213,11 +214,12 @@ macro_rules! step_identical_methods {
#[inline] #[inline]
#[allow(arithmetic_overflow)] #[allow(arithmetic_overflow)]
#[rustc_inherit_overflow_checks]
fn backward(start: Self, n: usize) -> Self { fn backward(start: Self, n: usize) -> Self {
// In debug builds, trigger a panic on overflow. // In debug builds, trigger a panic on overflow.
// This should optimize completely out in release builds. // This should optimize completely out in release builds.
if Self::backward_checked(start, n).is_none() { 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)`. // Do wrapping math to allow e.g. `Step::backward(127i8, 255)`.
start.wrapping_sub(n as Self) start.wrapping_sub(n as Self)

View file

@ -1,6 +1,5 @@
use crate::iter; use crate::iter;
use crate::num::Wrapping; use crate::num::Wrapping;
use crate::ops::{Add, Mul};
/// Trait to represent types that can be created by summing up an iterator. /// 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; 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 { macro_rules! integer_sum_product {
(@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
#[$attr] #[$attr]
impl Sum for $a { impl Sum for $a {
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self { 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] #[$attr]
impl Product for $a { impl Product for $a {
fn product<I: Iterator<Item=Self>>(iter: I) -> Self { 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] #[$attr]
impl<'a> Sum<&'a $a> for $a { impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self { 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] #[$attr]
impl<'a> Product<&'a $a> for $a { impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self { 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")] #[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Sum for $a { impl Sum for $a {
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self { 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")] #[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Product for $a { impl Product for $a {
fn product<I: Iterator<Item=Self>>(iter: I) -> Self { 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")] #[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Sum<&'a $a> for $a { impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self { 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")] #[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Product<&'a $a> for $a { impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self { 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. // can't split that into multiple files.
use crate::cmp::{self, Ordering}; use crate::cmp::{self, Ordering};
use crate::ops::{Add, ControlFlow, Try}; use crate::ops::{ControlFlow, Try};
use super::super::TrustedRandomAccess; use super::super::TrustedRandomAccess;
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
@ -242,13 +242,11 @@ pub trait Iterator {
where where
Self: Sized, Self: Sized,
{ {
#[inline] self.fold(
fn add1<T>(count: usize, _: T) -> usize { 0,
// Might overflow. #[rustc_inherit_overflow_checks]
Add::add(count, 1) |count, _| count + 1,
} )
self.fold(0, add1)
} }
/// Consumes the iterator, returning the last element. /// Consumes the iterator, returning the last element.
@ -2475,13 +2473,9 @@ pub trait Iterator {
fn check<T>( fn check<T>(
mut predicate: impl FnMut(T) -> bool, mut predicate: impl FnMut(T) -> bool,
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> { ) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
// The addition might panic on overflow #[rustc_inherit_overflow_checks]
move |i, x| { move |i, x| {
if predicate(x) { if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i + 1) }
ControlFlow::Break(i)
} else {
ControlFlow::Continue(Add::add(i, 1))
}
} }
} }