diff --git a/RELEASES.md b/RELEASES.md index 9001f9c4b00f0..4b753a2b32fff 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -113,6 +113,7 @@ Compatibility Notes 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 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 ------------- diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 01a57bea14e3b..c5f3a9d3379a7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -124,12 +124,7 @@ pub fn expand_deriving_rustc_encodable( explicit_self: borrowed_explicit_self(), args: vec![( Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - // FIXME: we could use `sym::s` here, but making `s` a static - // 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"), + sym::s, )], ret_ty: Literal(Path::new_( pathvec_std!(result::Result), diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index eca84c791fb3f..e85392cf0bda5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -525,8 +525,11 @@ impl CheckAttrVisitor<'tcx> { self.doc_attr_str_error(meta, "keyword"); return false; } - match self.tcx.hir().expect_item(hir_id).kind { - ItemKind::Mod(ref module) => { + match self.tcx.hir().find(hir_id).and_then(|node| match node { + hir::Node::Item(item) => Some(&item.kind), + _ => None, + }) { + Some(ItemKind::Mod(ref module)) => { if !module.item_ids.is_empty() { self.tcx .sess diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a96d37c652d12..862bde3f6a3e8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1062,6 +1062,7 @@ symbols! { rustdoc, rustfmt, rvalue_static_promotion, + s, sanitize, sanitizer_runtime, saturating_add, diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index c16d27fa1f58c..21bd79611a5e5 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -876,4 +876,40 @@ impl f32 { pub fn atanh(self) -> f32 { 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)) + } + } } diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 0d4b865f3392a..fe66a73afd63a 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -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(&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); +} diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 4c95df5ffe04a..8c8cf73741b51 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -879,6 +879,42 @@ impl f64 { 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 // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 5c163cfe90e0b..04cb0109261a4 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -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(&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); +} diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index d8021d3e99a70..32d194d961652 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -438,7 +438,13 @@ impl Seek for BufReader { } impl SizeHint for BufReader { + #[inline] fn lower_bound(&self) -> usize { - self.buffer().len() + SizeHint::lower_bound(self.get_ref()) + self.buffer().len() + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(self.get_ref()).and_then(|up| self.buffer().len().checked_add(up)) } } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index f57529767a91a..a25ef8c87a5d2 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -252,6 +252,7 @@ mod tests; use crate::cmp; +use crate::convert::TryInto; use crate::fmt; use crate::mem::replace; use crate::ops::{Deref, DerefMut}; @@ -2342,13 +2343,15 @@ impl BufRead for Chain { } impl SizeHint for Chain { + #[inline] fn lower_bound(&self) -> usize { SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second) } + #[inline] fn upper_bound(&self) -> Option { 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, } } @@ -2553,6 +2556,21 @@ impl BufRead for Take { } } +impl SizeHint for Take { + #[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 { + 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. /// /// This struct is generally created by calling [`bytes`] on a reader. @@ -2597,15 +2615,53 @@ trait SizeHint { } impl SizeHint for T { + #[inline] default fn lower_bound(&self) -> usize { 0 } + #[inline] default fn upper_bound(&self) -> Option { None } } +impl SizeHint for &mut T { + #[inline] + fn lower_bound(&self) -> usize { + SizeHint::lower_bound(*self) + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(*self) + } +} + +impl SizeHint for Box { + #[inline] + fn lower_bound(&self) -> usize { + SizeHint::lower_bound(&**self) + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(&**self) + } +} + +impl SizeHint for &[u8] { + #[inline] + fn lower_bound(&self) -> usize { + self.len() + } + + #[inline] + fn upper_bound(&self) -> Option { + Some(self.len()) + } +} + /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index df0dc7e9d31f6..2ee30f5fb4f08 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -224,6 +224,24 @@ fn empty_size_hint() { 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] fn chain_empty_size_hint() { 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 size_hint = chain.bytes().size_hint(); - assert_eq!(size_hint, (testdata.len(), None)); + assert_eq!(size_hint, (testdata.len(), Some(testdata.len()))); } #[test] diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 73f2f3eb3f5dc..f3bff391fb3ea 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -83,6 +83,7 @@ impl fmt::Debug for Empty { } impl SizeHint for Empty { + #[inline] fn upper_bound(&self) -> Option { 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 { + None + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6b2f49cfe48c9..664cc748ca6db 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -268,6 +268,7 @@ #![feature(exhaustive_patterns)] #![feature(extend_one)] #![cfg_attr(bootstrap, feature(extended_key_value_attributes))] +#![feature(float_interpolation)] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 15ce7056fea34..cd429d1426937 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -32,23 +32,8 @@ pub(super) fn recv_vectored_with_ancillary_from( msg.msg_name = &mut msg_name as *mut _ as *mut _; msg.msg_namelen = size_of::() as libc::socklen_t; msg.msg_iov = bufs.as_mut_ptr().cast(); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - 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; - } - } + msg.msg_iovlen = bufs.len() as _; + msg.msg_controllen = ancillary.buffer.len() as _; // macos requires that the control pointer is null when the len is 0. if msg.msg_controllen > 0 { 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_namelen = msg_namelen; msg.msg_iov = bufs.as_ptr() as *mut _; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - 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; - } - } + msg.msg_iovlen = bufs.len() as _; + msg.msg_controllen = ancillary.length as _; // macos requires that the control pointer is null when the len is 0. if msg.msg_controllen > 0 { msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); @@ -144,21 +114,7 @@ fn add_to_ancillary_data( let mut msg: libc::msghdr = zeroed(); msg.msg_control = buffer.as_mut_ptr().cast(); - cfg_if::cfg_if! { - 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; - } - } + msg.msg_controllen = *length as _; let mut cmsg = libc::CMSG_FIRSTHDR(&msg); let mut previous_cmsg = cmsg; @@ -180,21 +136,7 @@ fn add_to_ancillary_data( (*previous_cmsg).cmsg_level = cmsg_level; (*previous_cmsg).cmsg_type = cmsg_type; - cfg_if::cfg_if! { - 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; - } - } + (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as _; 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 { unsafe { - cfg_if::cfg_if! { - if #[cfg(any( - 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 cmsg_len_zero = libc::CMSG_LEN(0) as usize; + let data_len = (*cmsg).cmsg_len as usize - cmsg_len_zero; 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 { libc::SOL_SOCKET => match (*cmsg).cmsg_type { @@ -419,21 +343,7 @@ impl<'a> Iterator for Messages<'a> { unsafe { let mut msg: libc::msghdr = zeroed(); msg.msg_control = self.buffer.as_ptr() as *mut _; - cfg_if::cfg_if! { - 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; - } - } + msg.msg_controllen = self.buffer.len() as _; let cmsg = if let Some(current) = self.current { libc::CMSG_NXTHDR(&msg, current) diff --git a/src/test/ui/rustdoc/doc_keyword.rs b/src/test/ui/rustdoc/doc_keyword.rs index 4c72e7e96842c..4518f77ef933d 100644 --- a/src/test/ui/rustdoc/doc_keyword.rs +++ b/src/test/ui/rustdoc/doc_keyword.rs @@ -10,3 +10,11 @@ mod foo { #[doc(keyword = "hall")] //~ ERROR 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() {} +} diff --git a/src/test/ui/rustdoc/doc_keyword.stderr b/src/test/ui/rustdoc/doc_keyword.stderr index 0679bb8c5a7a6..6ba7034d54122 100644 --- a/src/test/ui/rustdoc/doc_keyword.stderr +++ b/src/test/ui/rustdoc/doc_keyword.stderr @@ -10,11 +10,17 @@ error: `#[doc(keyword = "...")]` can only be used on modules 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 --> $DIR/doc_keyword.rs:4:8 | LL | #![doc(keyword = "hello")] | ^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors