Auto merge of #86417 - m-ou-se:rollup-vo2y1rz, r=m-ou-se
Rollup of 6 pull requests Successful merges: - #85925 (Linear interpolation) - #86202 (Specialize `io::Bytes::size_hint` for more types) - #86357 (Rely on libc for correct integer types in os/unix/net/ancillary.rs.) - #86388 (Make `s` pre-interned) - #86401 (Fix ICE when using `#[doc(keyword = "...")]` on non-items) - #86405 (Add incr-comp note for 1.53.0 relnotes) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a6bc43ea84
16 changed files with 320 additions and 112 deletions
|
@ -113,6 +113,7 @@ Compatibility Notes
|
||||||
In particular, this was known to be a problem in the `lexical-core` crate,
|
In particular, this was known to be a problem in the `lexical-core` crate,
|
||||||
but they have published fixes for semantic versions 0.4 through 0.7. To
|
but they have published fixes for semantic versions 0.4 through 0.7. To
|
||||||
update this dependency alone, use `cargo update -p lexical-core`.
|
update this dependency alone, use `cargo update -p lexical-core`.
|
||||||
|
- Incremental compilation remains off by default, unless one uses the `RUSTC_FORCE_INCREMENTAL=1` environment variable added in 1.52.1.
|
||||||
|
|
||||||
Internal Only
|
Internal Only
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -124,12 +124,7 @@ pub fn expand_deriving_rustc_encodable(
|
||||||
explicit_self: borrowed_explicit_self(),
|
explicit_self: borrowed_explicit_self(),
|
||||||
args: vec![(
|
args: vec![(
|
||||||
Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
|
Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
|
||||||
// FIXME: we could use `sym::s` here, but making `s` a static
|
sym::s,
|
||||||
// symbol changes the symbol index ordering in a way that makes
|
|
||||||
// ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs
|
|
||||||
// fail. The linting code should be fixed so that its output
|
|
||||||
// does not depend on the symbol index ordering.
|
|
||||||
Symbol::intern("s"),
|
|
||||||
)],
|
)],
|
||||||
ret_ty: Literal(Path::new_(
|
ret_ty: Literal(Path::new_(
|
||||||
pathvec_std!(result::Result),
|
pathvec_std!(result::Result),
|
||||||
|
|
|
@ -525,8 +525,11 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
self.doc_attr_str_error(meta, "keyword");
|
self.doc_attr_str_error(meta, "keyword");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
match self.tcx.hir().expect_item(hir_id).kind {
|
match self.tcx.hir().find(hir_id).and_then(|node| match node {
|
||||||
ItemKind::Mod(ref module) => {
|
hir::Node::Item(item) => Some(&item.kind),
|
||||||
|
_ => None,
|
||||||
|
}) {
|
||||||
|
Some(ItemKind::Mod(ref module)) => {
|
||||||
if !module.item_ids.is_empty() {
|
if !module.item_ids.is_empty() {
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
|
|
|
@ -1062,6 +1062,7 @@ symbols! {
|
||||||
rustdoc,
|
rustdoc,
|
||||||
rustfmt,
|
rustfmt,
|
||||||
rvalue_static_promotion,
|
rvalue_static_promotion,
|
||||||
|
s,
|
||||||
sanitize,
|
sanitize,
|
||||||
sanitizer_runtime,
|
sanitizer_runtime,
|
||||||
saturating_add,
|
saturating_add,
|
||||||
|
|
|
@ -876,4 +876,40 @@ impl f32 {
|
||||||
pub fn atanh(self) -> f32 {
|
pub fn atanh(self) -> f32 {
|
||||||
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Linear interpolation between `start` and `end`.
|
||||||
|
///
|
||||||
|
/// This enables linear interpolation between `start` and `end`, where start is represented by
|
||||||
|
/// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all
|
||||||
|
/// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0
|
||||||
|
/// at a given rate, the result will change from `start` to `end` at a similar rate.
|
||||||
|
///
|
||||||
|
/// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the
|
||||||
|
/// range from `start` to `end`. This also is useful for transition functions which might
|
||||||
|
/// move slightly past the end or start for a desired effect. Mathematically, the values
|
||||||
|
/// returned are equivalent to `start + self * (end - start)`, although we make a few specific
|
||||||
|
/// guarantees that are useful specifically to linear interpolation.
|
||||||
|
///
|
||||||
|
/// These guarantees are:
|
||||||
|
///
|
||||||
|
/// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the
|
||||||
|
/// value at 1.0 is always `end`. (exactness)
|
||||||
|
/// * If `start` and `end` are [finite], the values will always move in the direction from
|
||||||
|
/// `start` to `end` (monotonicity)
|
||||||
|
/// * If `self` is [finite] and `start == end`, the value at any point will always be
|
||||||
|
/// `start == end`. (consistency)
|
||||||
|
///
|
||||||
|
/// [finite]: #method.is_finite
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
|
#[unstable(feature = "float_interpolation", issue = "86269")]
|
||||||
|
pub fn lerp(self, start: f32, end: f32) -> f32 {
|
||||||
|
// consistent
|
||||||
|
if start == end {
|
||||||
|
start
|
||||||
|
|
||||||
|
// exact/monotonic
|
||||||
|
} else {
|
||||||
|
self.mul_add(end, (-self).mul_add(start, start))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -757,3 +757,66 @@ fn test_total_cmp() {
|
||||||
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
|
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
|
||||||
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
|
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_exact() {
|
||||||
|
// simple values
|
||||||
|
assert_eq!(f32::lerp(0.0, 2.0, 4.0), 2.0);
|
||||||
|
assert_eq!(f32::lerp(1.0, 2.0, 4.0), 4.0);
|
||||||
|
|
||||||
|
// boundary values
|
||||||
|
assert_eq!(f32::lerp(0.0, f32::MIN, f32::MAX), f32::MIN);
|
||||||
|
assert_eq!(f32::lerp(1.0, f32::MIN, f32::MAX), f32::MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_consistent() {
|
||||||
|
assert_eq!(f32::lerp(f32::MAX, f32::MIN, f32::MIN), f32::MIN);
|
||||||
|
assert_eq!(f32::lerp(f32::MIN, f32::MAX, f32::MAX), f32::MAX);
|
||||||
|
|
||||||
|
// as long as t is finite, a/b can be infinite
|
||||||
|
assert_eq!(f32::lerp(f32::MAX, f32::NEG_INFINITY, f32::NEG_INFINITY), f32::NEG_INFINITY);
|
||||||
|
assert_eq!(f32::lerp(f32::MIN, f32::INFINITY, f32::INFINITY), f32::INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_nan_infinite() {
|
||||||
|
// non-finite t is not NaN if a/b different
|
||||||
|
assert!(!f32::lerp(f32::INFINITY, f32::MIN, f32::MAX).is_nan());
|
||||||
|
assert!(!f32::lerp(f32::NEG_INFINITY, f32::MIN, f32::MAX).is_nan());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_values() {
|
||||||
|
// just a few basic values
|
||||||
|
assert_eq!(f32::lerp(0.25, 1.0, 2.0), 1.25);
|
||||||
|
assert_eq!(f32::lerp(0.50, 1.0, 2.0), 1.50);
|
||||||
|
assert_eq!(f32::lerp(0.75, 1.0, 2.0), 1.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_monotonic() {
|
||||||
|
// near 0
|
||||||
|
let below_zero = f32::lerp(-f32::EPSILON, f32::MIN, f32::MAX);
|
||||||
|
let zero = f32::lerp(0.0, f32::MIN, f32::MAX);
|
||||||
|
let above_zero = f32::lerp(f32::EPSILON, f32::MIN, f32::MAX);
|
||||||
|
assert!(below_zero <= zero);
|
||||||
|
assert!(zero <= above_zero);
|
||||||
|
assert!(below_zero <= above_zero);
|
||||||
|
|
||||||
|
// near 0.5
|
||||||
|
let below_half = f32::lerp(0.5 - f32::EPSILON, f32::MIN, f32::MAX);
|
||||||
|
let half = f32::lerp(0.5, f32::MIN, f32::MAX);
|
||||||
|
let above_half = f32::lerp(0.5 + f32::EPSILON, f32::MIN, f32::MAX);
|
||||||
|
assert!(below_half <= half);
|
||||||
|
assert!(half <= above_half);
|
||||||
|
assert!(below_half <= above_half);
|
||||||
|
|
||||||
|
// near 1
|
||||||
|
let below_one = f32::lerp(1.0 - f32::EPSILON, f32::MIN, f32::MAX);
|
||||||
|
let one = f32::lerp(1.0, f32::MIN, f32::MAX);
|
||||||
|
let above_one = f32::lerp(1.0 + f32::EPSILON, f32::MIN, f32::MAX);
|
||||||
|
assert!(below_one <= one);
|
||||||
|
assert!(one <= above_one);
|
||||||
|
assert!(below_one <= above_one);
|
||||||
|
}
|
||||||
|
|
|
@ -879,6 +879,42 @@ impl f64 {
|
||||||
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Linear interpolation between `start` and `end`.
|
||||||
|
///
|
||||||
|
/// This enables linear interpolation between `start` and `end`, where start is represented by
|
||||||
|
/// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all
|
||||||
|
/// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0
|
||||||
|
/// at a given rate, the result will change from `start` to `end` at a similar rate.
|
||||||
|
///
|
||||||
|
/// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the
|
||||||
|
/// range from `start` to `end`. This also is useful for transition functions which might
|
||||||
|
/// move slightly past the end or start for a desired effect. Mathematically, the values
|
||||||
|
/// returned are equivalent to `start + self * (end - start)`, although we make a few specific
|
||||||
|
/// guarantees that are useful specifically to linear interpolation.
|
||||||
|
///
|
||||||
|
/// These guarantees are:
|
||||||
|
///
|
||||||
|
/// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the
|
||||||
|
/// value at 1.0 is always `end`. (exactness)
|
||||||
|
/// * If `start` and `end` are [finite], the values will always move in the direction from
|
||||||
|
/// `start` to `end` (monotonicity)
|
||||||
|
/// * If `self` is [finite] and `start == end`, the value at any point will always be
|
||||||
|
/// `start == end`. (consistency)
|
||||||
|
///
|
||||||
|
/// [finite]: #method.is_finite
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
|
#[unstable(feature = "float_interpolation", issue = "86269")]
|
||||||
|
pub fn lerp(self, start: f64, end: f64) -> f64 {
|
||||||
|
// consistent
|
||||||
|
if start == end {
|
||||||
|
start
|
||||||
|
|
||||||
|
// exact/monotonic
|
||||||
|
} else {
|
||||||
|
self.mul_add(end, (-self).mul_add(start, start))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Solaris/Illumos requires a wrapper around log, log2, and log10 functions
|
// Solaris/Illumos requires a wrapper around log, log2, and log10 functions
|
||||||
// because of their non-standard behavior (e.g., log(-n) returns -Inf instead
|
// because of their non-standard behavior (e.g., log(-n) returns -Inf instead
|
||||||
// of expected NaN).
|
// of expected NaN).
|
||||||
|
|
|
@ -753,3 +753,58 @@ fn test_total_cmp() {
|
||||||
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
|
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
|
||||||
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
|
assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_exact() {
|
||||||
|
// simple values
|
||||||
|
assert_eq!(f64::lerp(0.0, 2.0, 4.0), 2.0);
|
||||||
|
assert_eq!(f64::lerp(1.0, 2.0, 4.0), 4.0);
|
||||||
|
|
||||||
|
// boundary values
|
||||||
|
assert_eq!(f64::lerp(0.0, f64::MIN, f64::MAX), f64::MIN);
|
||||||
|
assert_eq!(f64::lerp(1.0, f64::MIN, f64::MAX), f64::MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_consistent() {
|
||||||
|
assert_eq!(f64::lerp(f64::MAX, f64::MIN, f64::MIN), f64::MIN);
|
||||||
|
assert_eq!(f64::lerp(f64::MIN, f64::MAX, f64::MAX), f64::MAX);
|
||||||
|
|
||||||
|
// as long as t is finite, a/b can be infinite
|
||||||
|
assert_eq!(f64::lerp(f64::MAX, f64::NEG_INFINITY, f64::NEG_INFINITY), f64::NEG_INFINITY);
|
||||||
|
assert_eq!(f64::lerp(f64::MIN, f64::INFINITY, f64::INFINITY), f64::INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_nan_infinite() {
|
||||||
|
// non-finite t is not NaN if a/b different
|
||||||
|
assert!(!f64::lerp(f64::INFINITY, f64::MIN, f64::MAX).is_nan());
|
||||||
|
assert!(!f64::lerp(f64::NEG_INFINITY, f64::MIN, f64::MAX).is_nan());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_values() {
|
||||||
|
// just a few basic values
|
||||||
|
assert_eq!(f64::lerp(0.25, 1.0, 2.0), 1.25);
|
||||||
|
assert_eq!(f64::lerp(0.50, 1.0, 2.0), 1.50);
|
||||||
|
assert_eq!(f64::lerp(0.75, 1.0, 2.0), 1.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lerp_monotonic() {
|
||||||
|
// near 0
|
||||||
|
let below_zero = f64::lerp(-f64::EPSILON, f64::MIN, f64::MAX);
|
||||||
|
let zero = f64::lerp(0.0, f64::MIN, f64::MAX);
|
||||||
|
let above_zero = f64::lerp(f64::EPSILON, f64::MIN, f64::MAX);
|
||||||
|
assert!(below_zero <= zero);
|
||||||
|
assert!(zero <= above_zero);
|
||||||
|
assert!(below_zero <= above_zero);
|
||||||
|
|
||||||
|
// near 1
|
||||||
|
let below_one = f64::lerp(1.0 - f64::EPSILON, f64::MIN, f64::MAX);
|
||||||
|
let one = f64::lerp(1.0, f64::MIN, f64::MAX);
|
||||||
|
let above_one = f64::lerp(1.0 + f64::EPSILON, f64::MIN, f64::MAX);
|
||||||
|
assert!(below_one <= one);
|
||||||
|
assert!(one <= above_one);
|
||||||
|
assert!(below_one <= above_one);
|
||||||
|
}
|
||||||
|
|
|
@ -438,7 +438,13 @@ impl<R: Seek> Seek for BufReader<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SizeHint for BufReader<T> {
|
impl<T> SizeHint for BufReader<T> {
|
||||||
|
#[inline]
|
||||||
fn lower_bound(&self) -> usize {
|
fn lower_bound(&self) -> usize {
|
||||||
self.buffer().len()
|
SizeHint::lower_bound(self.get_ref()) + self.buffer().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
|
SizeHint::upper_bound(self.get_ref()).and_then(|up| self.buffer().len().checked_add(up))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,7 @@
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::cmp;
|
use crate::cmp;
|
||||||
|
use crate::convert::TryInto;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::mem::replace;
|
use crate::mem::replace;
|
||||||
use crate::ops::{Deref, DerefMut};
|
use crate::ops::{Deref, DerefMut};
|
||||||
|
@ -2342,13 +2343,15 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> SizeHint for Chain<T, U> {
|
impl<T, U> SizeHint for Chain<T, U> {
|
||||||
|
#[inline]
|
||||||
fn lower_bound(&self) -> usize {
|
fn lower_bound(&self) -> usize {
|
||||||
SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second)
|
SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn upper_bound(&self) -> Option<usize> {
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) {
|
match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) {
|
||||||
(Some(first), Some(second)) => Some(first + second),
|
(Some(first), Some(second)) => first.checked_add(second),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2553,6 +2556,21 @@ impl<T: BufRead> BufRead for Take<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> SizeHint for Take<T> {
|
||||||
|
#[inline]
|
||||||
|
fn lower_bound(&self) -> usize {
|
||||||
|
cmp::min(SizeHint::lower_bound(&self.inner) as u64, self.limit) as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
|
match SizeHint::upper_bound(&self.inner) {
|
||||||
|
Some(upper_bound) => Some(cmp::min(upper_bound as u64, self.limit) as usize),
|
||||||
|
None => self.limit.try_into().ok(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An iterator over `u8` values of a reader.
|
/// An iterator over `u8` values of a reader.
|
||||||
///
|
///
|
||||||
/// This struct is generally created by calling [`bytes`] on a reader.
|
/// This struct is generally created by calling [`bytes`] on a reader.
|
||||||
|
@ -2597,15 +2615,53 @@ trait SizeHint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SizeHint for T {
|
impl<T> SizeHint for T {
|
||||||
|
#[inline]
|
||||||
default fn lower_bound(&self) -> usize {
|
default fn lower_bound(&self) -> usize {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
default fn upper_bound(&self) -> Option<usize> {
|
default fn upper_bound(&self) -> Option<usize> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> SizeHint for &mut T {
|
||||||
|
#[inline]
|
||||||
|
fn lower_bound(&self) -> usize {
|
||||||
|
SizeHint::lower_bound(*self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
|
SizeHint::upper_bound(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SizeHint for Box<T> {
|
||||||
|
#[inline]
|
||||||
|
fn lower_bound(&self) -> usize {
|
||||||
|
SizeHint::lower_bound(&**self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
|
SizeHint::upper_bound(&**self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SizeHint for &[u8] {
|
||||||
|
#[inline]
|
||||||
|
fn lower_bound(&self) -> usize {
|
||||||
|
self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
|
Some(self.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An iterator over the contents of an instance of `BufRead` split on a
|
/// An iterator over the contents of an instance of `BufRead` split on a
|
||||||
/// particular byte.
|
/// particular byte.
|
||||||
///
|
///
|
||||||
|
|
|
@ -224,6 +224,24 @@ fn empty_size_hint() {
|
||||||
assert_eq!(size_hint, (0, Some(0)));
|
assert_eq!(size_hint, (0, Some(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slice_size_hint() {
|
||||||
|
let size_hint = (&[1, 2, 3]).bytes().size_hint();
|
||||||
|
assert_eq!(size_hint, (3, Some(3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn take_size_hint() {
|
||||||
|
let size_hint = (&[1, 2, 3]).take(2).bytes().size_hint();
|
||||||
|
assert_eq!(size_hint, (2, Some(2)));
|
||||||
|
|
||||||
|
let size_hint = (&[1, 2, 3]).take(4).bytes().size_hint();
|
||||||
|
assert_eq!(size_hint, (3, Some(3)));
|
||||||
|
|
||||||
|
let size_hint = io::repeat(0).take(3).bytes().size_hint();
|
||||||
|
assert_eq!(size_hint, (3, Some(3)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn chain_empty_size_hint() {
|
fn chain_empty_size_hint() {
|
||||||
let chain = io::empty().chain(io::empty());
|
let chain = io::empty().chain(io::empty());
|
||||||
|
@ -242,7 +260,7 @@ fn chain_size_hint() {
|
||||||
|
|
||||||
let chain = buf_reader_1.chain(buf_reader_2);
|
let chain = buf_reader_1.chain(buf_reader_2);
|
||||||
let size_hint = chain.bytes().size_hint();
|
let size_hint = chain.bytes().size_hint();
|
||||||
assert_eq!(size_hint, (testdata.len(), None));
|
assert_eq!(size_hint, (testdata.len(), Some(testdata.len())));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -83,6 +83,7 @@ impl fmt::Debug for Empty {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeHint for Empty {
|
impl SizeHint for Empty {
|
||||||
|
#[inline]
|
||||||
fn upper_bound(&self) -> Option<usize> {
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
|
@ -147,6 +148,18 @@ impl Read for Repeat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SizeHint for Repeat {
|
||||||
|
#[inline]
|
||||||
|
fn lower_bound(&self) -> usize {
|
||||||
|
usize::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn upper_bound(&self) -> Option<usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||||
impl fmt::Debug for Repeat {
|
impl fmt::Debug for Repeat {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
|
|
@ -268,6 +268,7 @@
|
||||||
#![feature(exhaustive_patterns)]
|
#![feature(exhaustive_patterns)]
|
||||||
#![feature(extend_one)]
|
#![feature(extend_one)]
|
||||||
#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
|
#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
|
||||||
|
#![feature(float_interpolation)]
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
#![feature(format_args_nl)]
|
#![feature(format_args_nl)]
|
||||||
#![feature(gen_future)]
|
#![feature(gen_future)]
|
||||||
|
|
|
@ -32,23 +32,8 @@ pub(super) fn recv_vectored_with_ancillary_from(
|
||||||
msg.msg_name = &mut msg_name as *mut _ as *mut _;
|
msg.msg_name = &mut msg_name as *mut _ as *mut _;
|
||||||
msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
|
msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
|
||||||
msg.msg_iov = bufs.as_mut_ptr().cast();
|
msg.msg_iov = bufs.as_mut_ptr().cast();
|
||||||
cfg_if::cfg_if! {
|
msg.msg_iovlen = bufs.len() as _;
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
msg.msg_controllen = ancillary.buffer.len() as _;
|
||||||
msg.msg_iovlen = bufs.len() as libc::size_t;
|
|
||||||
msg.msg_controllen = ancillary.buffer.len() as libc::size_t;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "emscripten",
|
|
||||||
target_os = "freebsd",
|
|
||||||
all(target_os = "linux", target_env = "musl",),
|
|
||||||
target_os = "macos",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))] {
|
|
||||||
msg.msg_iovlen = bufs.len() as libc::c_int;
|
|
||||||
msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// macos requires that the control pointer is null when the len is 0.
|
// macos requires that the control pointer is null when the len is 0.
|
||||||
if msg.msg_controllen > 0 {
|
if msg.msg_controllen > 0 {
|
||||||
msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
|
msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
|
||||||
|
@ -80,23 +65,8 @@ pub(super) fn send_vectored_with_ancillary_to(
|
||||||
msg.msg_name = &mut msg_name as *mut _ as *mut _;
|
msg.msg_name = &mut msg_name as *mut _ as *mut _;
|
||||||
msg.msg_namelen = msg_namelen;
|
msg.msg_namelen = msg_namelen;
|
||||||
msg.msg_iov = bufs.as_ptr() as *mut _;
|
msg.msg_iov = bufs.as_ptr() as *mut _;
|
||||||
cfg_if::cfg_if! {
|
msg.msg_iovlen = bufs.len() as _;
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
msg.msg_controllen = ancillary.length as _;
|
||||||
msg.msg_iovlen = bufs.len() as libc::size_t;
|
|
||||||
msg.msg_controllen = ancillary.length as libc::size_t;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "emscripten",
|
|
||||||
target_os = "freebsd",
|
|
||||||
all(target_os = "linux", target_env = "musl",),
|
|
||||||
target_os = "macos",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))] {
|
|
||||||
msg.msg_iovlen = bufs.len() as libc::c_int;
|
|
||||||
msg.msg_controllen = ancillary.length as libc::socklen_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// macos requires that the control pointer is null when the len is 0.
|
// macos requires that the control pointer is null when the len is 0.
|
||||||
if msg.msg_controllen > 0 {
|
if msg.msg_controllen > 0 {
|
||||||
msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
|
msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
|
||||||
|
@ -144,21 +114,7 @@ fn add_to_ancillary_data<T>(
|
||||||
|
|
||||||
let mut msg: libc::msghdr = zeroed();
|
let mut msg: libc::msghdr = zeroed();
|
||||||
msg.msg_control = buffer.as_mut_ptr().cast();
|
msg.msg_control = buffer.as_mut_ptr().cast();
|
||||||
cfg_if::cfg_if! {
|
msg.msg_controllen = *length as _;
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
|
||||||
msg.msg_controllen = *length as libc::size_t;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "emscripten",
|
|
||||||
target_os = "freebsd",
|
|
||||||
all(target_os = "linux", target_env = "musl",),
|
|
||||||
target_os = "macos",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))] {
|
|
||||||
msg.msg_controllen = *length as libc::socklen_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut cmsg = libc::CMSG_FIRSTHDR(&msg);
|
let mut cmsg = libc::CMSG_FIRSTHDR(&msg);
|
||||||
let mut previous_cmsg = cmsg;
|
let mut previous_cmsg = cmsg;
|
||||||
|
@ -180,21 +136,7 @@ fn add_to_ancillary_data<T>(
|
||||||
|
|
||||||
(*previous_cmsg).cmsg_level = cmsg_level;
|
(*previous_cmsg).cmsg_level = cmsg_level;
|
||||||
(*previous_cmsg).cmsg_type = cmsg_type;
|
(*previous_cmsg).cmsg_type = cmsg_type;
|
||||||
cfg_if::cfg_if! {
|
(*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as _;
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
|
||||||
(*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::size_t;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "emscripten",
|
|
||||||
target_os = "freebsd",
|
|
||||||
all(target_os = "linux", target_env = "musl",),
|
|
||||||
target_os = "macos",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))] {
|
|
||||||
(*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::socklen_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = libc::CMSG_DATA(previous_cmsg).cast();
|
let data = libc::CMSG_DATA(previous_cmsg).cast();
|
||||||
|
|
||||||
|
@ -364,28 +306,10 @@ impl<'a> AncillaryData<'a> {
|
||||||
|
|
||||||
fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
|
fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
cfg_if::cfg_if! {
|
let cmsg_len_zero = libc::CMSG_LEN(0) as usize;
|
||||||
if #[cfg(any(
|
let data_len = (*cmsg).cmsg_len as usize - cmsg_len_zero;
|
||||||
target_os = "android",
|
|
||||||
all(target_os = "linux", target_env = "gnu"),
|
|
||||||
all(target_os = "linux", target_env = "uclibc"),
|
|
||||||
))] {
|
|
||||||
let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "emscripten",
|
|
||||||
target_os = "freebsd",
|
|
||||||
all(target_os = "linux", target_env = "musl",),
|
|
||||||
target_os = "macos",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))] {
|
|
||||||
let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let data_len = (*cmsg).cmsg_len - cmsg_len_zero;
|
|
||||||
let data = libc::CMSG_DATA(cmsg).cast();
|
let data = libc::CMSG_DATA(cmsg).cast();
|
||||||
let data = from_raw_parts(data, data_len as usize);
|
let data = from_raw_parts(data, data_len);
|
||||||
|
|
||||||
match (*cmsg).cmsg_level {
|
match (*cmsg).cmsg_level {
|
||||||
libc::SOL_SOCKET => match (*cmsg).cmsg_type {
|
libc::SOL_SOCKET => match (*cmsg).cmsg_type {
|
||||||
|
@ -419,21 +343,7 @@ impl<'a> Iterator for Messages<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut msg: libc::msghdr = zeroed();
|
let mut msg: libc::msghdr = zeroed();
|
||||||
msg.msg_control = self.buffer.as_ptr() as *mut _;
|
msg.msg_control = self.buffer.as_ptr() as *mut _;
|
||||||
cfg_if::cfg_if! {
|
msg.msg_controllen = self.buffer.len() as _;
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
|
||||||
msg.msg_controllen = self.buffer.len() as libc::size_t;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "emscripten",
|
|
||||||
target_os = "freebsd",
|
|
||||||
all(target_os = "linux", target_env = "musl",),
|
|
||||||
target_os = "macos",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))] {
|
|
||||||
msg.msg_controllen = self.buffer.len() as libc::socklen_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cmsg = if let Some(current) = self.current {
|
let cmsg = if let Some(current) = self.current {
|
||||||
libc::CMSG_NXTHDR(&msg, current)
|
libc::CMSG_NXTHDR(&msg, current)
|
||||||
|
|
|
@ -10,3 +10,11 @@ mod foo {
|
||||||
|
|
||||||
#[doc(keyword = "hall")] //~ ERROR
|
#[doc(keyword = "hall")] //~ ERROR
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
|
|
||||||
|
|
||||||
|
// Regression test for the ICE described in #83512.
|
||||||
|
trait Foo {
|
||||||
|
#[doc(keyword = "match")]
|
||||||
|
//~^ ERROR: `#[doc(keyword = "...")]` can only be used on modules
|
||||||
|
fn quux() {}
|
||||||
|
}
|
||||||
|
|
|
@ -10,11 +10,17 @@ error: `#[doc(keyword = "...")]` can only be used on modules
|
||||||
LL | #[doc(keyword = "hall")]
|
LL | #[doc(keyword = "hall")]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[doc(keyword = "...")]` can only be used on modules
|
||||||
|
--> $DIR/doc_keyword.rs:17:11
|
||||||
|
|
|
||||||
|
LL | #[doc(keyword = "match")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute
|
error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute
|
||||||
--> $DIR/doc_keyword.rs:4:8
|
--> $DIR/doc_keyword.rs:4:8
|
||||||
|
|
|
|
||||||
LL | #![doc(keyword = "hello")]
|
LL | #![doc(keyword = "hello")]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue