提交 607d6b00 编写于 作者: B bors

Auto merge of #86321 - JohnTitor:rollup-q61c8q4, r=JohnTitor

Rollup of 10 pull requests

Successful merges:

 - #80269 (Explain non-dropped sender recv in docs)
 - #82179 (Add functions `Duration::try_from_secs_{f32, f64}`)
 - #85608 (Stabilize `ops::ControlFlow` (just the type))
 - #85792 (Refactor windows sockets impl methods)
 - #86220 (Improve maybe_uninit_extra docs)
 - #86277 (Remove must_use from ALLOWED_ATTRIBUTES)
 - #86285 ( rust-analyzer)
 - #86294 (Stabilize {std, core}::prelude::rust_*.)
 - #86306 (Add mailmap entries for myself)
 - #86314 (Remove trailing triple backticks in `mut_keyword` docs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
...@@ -166,6 +166,8 @@ lcnr <bastian_kauschke@hotmail.de> ...@@ -166,6 +166,8 @@ lcnr <bastian_kauschke@hotmail.de>
Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <lee@leejeffery.co.uk> Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <lee@leejeffery.co.uk>
Lee Wondong <wdlee91@gmail.com> Lee Wondong <wdlee91@gmail.com>
Lennart Kudling <github@kudling.de> Lennart Kudling <github@kudling.de>
Léo Lanteri Thauvin <leseulartichaut@gmail.com>
Léo Lanteri Thauvin <leseulartichaut@gmail.com> <38361244+LeSeulArtichaut@users.noreply.github.com>
Léo Testard <leo.testard@gmail.com> Léo Testard <leo.testard@gmail.com>
Lindsey Kuper <lindsey@composition.al> <lindsey@rockstargirl.org> Lindsey Kuper <lindsey@composition.al> <lindsey@rockstargirl.org>
Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com> Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com>
......
...@@ -331,7 +331,7 @@ pub fn lower_crate<'a, 'hir>( ...@@ -331,7 +331,7 @@ pub fn lower_crate<'a, 'hir>(
lifetimes_to_define: Vec::new(), lifetimes_to_define: Vec::new(),
is_collecting_in_band_lifetimes: false, is_collecting_in_band_lifetimes: false,
in_scope_lifetimes: Vec::new(), in_scope_lifetimes: Vec::new(),
allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()), allow_try_trait: Some([sym::try_trait_v2][..].into()),
allow_gen_future: Some([sym::gen_future][..].into()), allow_gen_future: Some([sym::gen_future][..].into()),
} }
.lower_crate(krate) .lower_crate(krate)
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(control_flow_enum)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(format_args_capture)] #![feature(format_args_capture)]
#![feature(iter_zip)] #![feature(iter_zip)]
......
...@@ -416,7 +416,6 @@ ...@@ -416,7 +416,6 @@
constructor, constructor,
contents, contents,
context, context,
control_flow_enum,
convert, convert,
copy, copy,
copy_closures, copy_closures,
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)] #![feature(in_band_lifetimes)]
#![feature(nll)] #![feature(nll)]
#![feature(control_flow_enum)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]
......
...@@ -1959,6 +1959,31 @@ fn is_partitioned<P>(mut self, mut predicate: P) -> bool ...@@ -1959,6 +1959,31 @@ fn is_partitioned<P>(mut self, mut predicate: P) -> bool
/// assert_eq!(it.len(), 2); /// assert_eq!(it.len(), 2);
/// assert_eq!(it.next(), Some(&40)); /// assert_eq!(it.next(), Some(&40));
/// ``` /// ```
///
/// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`]
/// type allows a similar idea:
///
/// ```
/// use std::ops::ControlFlow;
///
/// let triangular = (1..30).try_fold(0_i8, |prev, x| {
/// if let Some(next) = prev.checked_add(x) {
/// ControlFlow::Continue(next)
/// } else {
/// ControlFlow::Break(prev)
/// }
/// });
/// assert_eq!(triangular, ControlFlow::Break(120));
///
/// let triangular = (1..30).try_fold(0_u64, |prev, x| {
/// if let Some(next) = prev.checked_add(x) {
/// ControlFlow::Continue(next)
/// } else {
/// ControlFlow::Break(prev)
/// }
/// });
/// assert_eq!(triangular, ControlFlow::Continue(435));
/// ```
#[inline] #[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")] #[stable(feature = "iterator_try_fold", since = "1.27.0")]
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
...@@ -2001,6 +2026,22 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R ...@@ -2001,6 +2026,22 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
/// // It short-circuited, so the remaining items are still in the iterator: /// // It short-circuited, so the remaining items are still in the iterator:
/// assert_eq!(it.next(), Some("stale_bread.json")); /// assert_eq!(it.next(), Some("stale_bread.json"));
/// ``` /// ```
///
/// The [`crate::ops::ControlFlow`] type can be used with this method for the
/// situations in which you'd use `break` and `continue` in a normal loop:
///
/// ```
/// use std::ops::ControlFlow;
///
/// let r = (2..100).try_for_each(|x| {
/// if 323 % x == 0 {
/// return ControlFlow::Break(x)
/// }
///
/// ControlFlow::Continue(())
/// });
/// assert_eq!(r, ControlFlow::Break(17));
/// ```
#[inline] #[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")] #[stable(feature = "iterator_try_fold", since = "1.27.0")]
fn try_for_each<F, R>(&mut self, f: F) -> R fn try_for_each<F, R>(&mut self, f: F) -> R
......
...@@ -402,10 +402,60 @@ pub fn zeroed() -> MaybeUninit<T> { ...@@ -402,10 +402,60 @@ pub fn zeroed() -> MaybeUninit<T> {
u u
} }
/// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value /// Sets the value of the `MaybeUninit<T>`.
/// without dropping it, so be careful not to use this twice unless you want to ///
/// skip running the destructor. For your convenience, this also returns a mutable /// This overwrites any previous value without dropping it, so be careful
/// reference to the (now safely initialized) contents of `self`. /// not to use this twice unless you want to skip running the destructor.
/// For your convenience, this also returns a mutable reference to the
/// (now safely initialized) contents of `self`.
///
/// As the content is stored inside a `MaybeUninit`, the destructor is not
/// ran for the inner data if the MaybeUninit leaves scope without a call to
/// [`assume_init`], [`assume_init_drop`], or similar. Code that receives
/// the mutable reference returned by this function needs to keep this in
/// mind. The safety model of Rust regards leaks as safe, but they are
/// usually still undesirable. This being said, the mutable reference
/// behaves like any other mutable reference would, so assigning a new value
/// to it will drop the old content.
///
/// [`assume_init`]: Self::assume_init
/// [`assume_init_drop`]: Self::assume_init_drop
///
/// # Examples
///
/// Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit_extra)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u8>>::uninit();
///
/// {
/// let hello = x.write((&b"Hello, world!").to_vec());
/// // Setting hello does not leak prior allocations, but drops them
/// *hello = (&b"Hello").to_vec();
/// hello[0] = 'h' as u8;
/// }
/// // x is initialized now:
/// let s = unsafe { x.assume_init() };
/// assert_eq!(b"hello", s.as_slice());
/// ```
///
/// This usage of the method causes a leak:
///
/// ```rust
/// #![feature(maybe_uninit_extra)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<String>::uninit();
///
/// x.write("Hello".to_string());
/// // This leaks the contained string:
/// x.write("hello".to_string());
/// // x is initialized now:
/// let s = unsafe { x.assume_init() };
/// ```
#[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
#[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")] #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
#[inline(always)] #[inline(always)]
...@@ -564,9 +614,11 @@ pub const fn as_mut_ptr(&mut self) -> *mut T { ...@@ -564,9 +614,11 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
/// behavior. The [type-level documentation][inv] contains more information about /// behavior. The [type-level documentation][inv] contains more information about
/// this initialization invariant. /// this initialization invariant.
/// ///
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using /// Moreover, similar to the [`ptr::read`] function, this function creates a
/// multiple copies of the data (by calling `assume_init_read` multiple times, or first /// bitwise copy of the contents, regardless whether the contained type
/// calling `assume_init_read` and then [`assume_init`]), it is your responsibility /// implements the [`Copy`] trait or not. When using multiple copies of the
/// data (by calling `assume_init_read` multiple times, or first calling
/// `assume_init_read` and then [`assume_init`]), it is your responsibility
/// to ensure that that data may indeed be duplicated. /// to ensure that that data may indeed be duplicated.
/// ///
/// [inv]: #initialization-invariant /// [inv]: #initialization-invariant
...@@ -622,7 +674,8 @@ pub const fn as_mut_ptr(&mut self) -> *mut T { ...@@ -622,7 +674,8 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
/// Drops the contained value in place. /// Drops the contained value in place.
/// ///
/// If you have ownership of the `MaybeUninit`, you can use [`assume_init`] instead. /// If you have ownership of the `MaybeUninit`, you can also use
/// [`assume_init`] as an alternative.
/// ///
/// # Safety /// # Safety
/// ///
...@@ -632,11 +685,12 @@ pub const fn as_mut_ptr(&mut self) -> *mut T { ...@@ -632,11 +685,12 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
/// ///
/// On top of that, all additional invariants of the type `T` must be /// On top of that, all additional invariants of the type `T` must be
/// satisfied, as the `Drop` implementation of `T` (or its members) may /// satisfied, as the `Drop` implementation of `T` (or its members) may
/// rely on this. For example, a `1`-initialized [`Vec<T>`] is considered /// rely on this. For example, setting a [`Vec<T>`] to an invalid but
/// initialized (under the current implementation; this does not constitute /// non-null address makes it initialized (under the current implementation;
/// a stable guarantee) because the only requirement the compiler knows /// this does not constitute a stable guarantee), because the only
/// about it is that the data pointer must be non-null. Dropping such a /// requirement the compiler knows about it is that the data pointer must be
/// `Vec<T>` however will cause undefined behaviour. /// non-null. Dropping such a `Vec<T>` however will cause undefined
/// behaviour.
/// ///
/// [`assume_init`]: MaybeUninit::assume_init /// [`assume_init`]: MaybeUninit::assume_init
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
/// ///
/// Early-exiting from [`Iterator::try_for_each`]: /// Early-exiting from [`Iterator::try_for_each`]:
/// ``` /// ```
/// #![feature(control_flow_enum)]
/// use std::ops::ControlFlow; /// use std::ops::ControlFlow;
/// ///
/// let r = (2..100).try_for_each(|x| { /// let r = (2..100).try_for_each(|x| {
...@@ -26,7 +25,6 @@ ...@@ -26,7 +25,6 @@
/// ///
/// A basic tree traversal: /// A basic tree traversal:
/// ```no_run /// ```no_run
/// #![feature(control_flow_enum)]
/// use std::ops::ControlFlow; /// use std::ops::ControlFlow;
/// ///
/// pub struct TreeNode<T> { /// pub struct TreeNode<T> {
...@@ -48,13 +46,15 @@ ...@@ -48,13 +46,15 @@
/// } /// }
/// } /// }
/// ``` /// ```
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum ControlFlow<B, C = ()> { pub enum ControlFlow<B, C = ()> {
/// Move on to the next phase of the operation as normal. /// Move on to the next phase of the operation as normal.
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
#[cfg_attr(not(bootstrap), lang = "Continue")] #[cfg_attr(not(bootstrap), lang = "Continue")]
Continue(C), Continue(C),
/// Exit the operation without running subsequent phases. /// Exit the operation without running subsequent phases.
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
#[cfg_attr(not(bootstrap), lang = "Break")] #[cfg_attr(not(bootstrap), lang = "Break")]
Break(B), Break(B),
// Yes, the order of the variants doesn't match the type parameters. // Yes, the order of the variants doesn't match the type parameters.
......
...@@ -55,7 +55,6 @@ ...@@ -55,7 +55,6 @@
/// into the return type using [`Try::from_output`]: /// into the return type using [`Try::from_output`]:
/// ``` /// ```
/// # #![feature(try_trait_v2)] /// # #![feature(try_trait_v2)]
/// # #![feature(control_flow_enum)]
/// # use std::ops::{ControlFlow, Try}; /// # use std::ops::{ControlFlow, Try};
/// fn simple_try_fold_2<A, T, R: Try<Output = A>>( /// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
/// iter: impl Iterator<Item = T>, /// iter: impl Iterator<Item = T>,
...@@ -79,7 +78,6 @@ ...@@ -79,7 +78,6 @@
/// recreated from their corresponding residual, so we'll just call it: /// recreated from their corresponding residual, so we'll just call it:
/// ``` /// ```
/// # #![feature(try_trait_v2)] /// # #![feature(try_trait_v2)]
/// # #![feature(control_flow_enum)]
/// # use std::ops::{ControlFlow, Try}; /// # use std::ops::{ControlFlow, Try};
/// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>( /// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
/// iter: impl Iterator<Item = T>, /// iter: impl Iterator<Item = T>,
...@@ -170,7 +168,6 @@ pub trait Try: FromResidual { ...@@ -170,7 +168,6 @@ pub trait Try: FromResidual {
/// ///
/// ``` /// ```
/// #![feature(try_trait_v2)] /// #![feature(try_trait_v2)]
/// #![feature(control_flow_enum)]
/// use std::ops::Try; /// use std::ops::Try;
/// ///
/// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3)); /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
...@@ -202,7 +199,6 @@ pub trait Try: FromResidual { ...@@ -202,7 +199,6 @@ pub trait Try: FromResidual {
/// ///
/// ``` /// ```
/// #![feature(try_trait_v2)] /// #![feature(try_trait_v2)]
/// #![feature(control_flow_enum)]
/// use std::ops::{ControlFlow, Try}; /// use std::ops::{ControlFlow, Try};
/// ///
/// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
...@@ -329,7 +325,6 @@ pub trait FromResidual<R = <Self as Try>::Residual> { ...@@ -329,7 +325,6 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
/// ///
/// ``` /// ```
/// #![feature(try_trait_v2)] /// #![feature(try_trait_v2)]
/// #![feature(control_flow_enum)]
/// use std::ops::{ControlFlow, FromResidual}; /// use std::ops::{ControlFlow, FromResidual};
/// ///
/// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3)); /// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
/// The 2015 version of the core prelude. /// The 2015 version of the core prelude.
/// ///
/// See the [module-level documentation](self) for more. /// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2015", issue = "85684")] #[stable(feature = "prelude_2015", since = "1.55.0")]
pub mod rust_2015 { pub mod rust_2015 {
#[unstable(feature = "prelude_2015", issue = "85684")] #[stable(feature = "prelude_2015", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use super::v1::*; pub use super::v1::*;
} }
...@@ -21,9 +21,9 @@ pub mod rust_2015 { ...@@ -21,9 +21,9 @@ pub mod rust_2015 {
/// The 2018 version of the core prelude. /// The 2018 version of the core prelude.
/// ///
/// See the [module-level documentation](self) for more. /// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2018", issue = "85684")] #[stable(feature = "prelude_2018", since = "1.55.0")]
pub mod rust_2018 { pub mod rust_2018 {
#[unstable(feature = "prelude_2018", issue = "85684")] #[stable(feature = "prelude_2018", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use super::v1::*; pub use super::v1::*;
} }
...@@ -31,17 +31,17 @@ pub mod rust_2018 { ...@@ -31,17 +31,17 @@ pub mod rust_2018 {
/// The 2021 version of the core prelude. /// The 2021 version of the core prelude.
/// ///
/// See the [module-level documentation](self) for more. /// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
pub mod rust_2021 { pub mod rust_2021 {
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use super::v1::*; pub use super::v1::*;
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::iter::FromIterator; pub use crate::iter::FromIterator;
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::convert::{TryFrom, TryInto}; pub use crate::convert::{TryFrom, TryInto};
} }
...@@ -687,21 +687,47 @@ pub const fn as_secs_f32(&self) -> f32 { ...@@ -687,21 +687,47 @@ pub const fn as_secs_f32(&self) -> f32 {
#[inline] #[inline]
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn from_secs_f64(secs: f64) -> Duration { pub const fn from_secs_f64(secs: f64) -> Duration {
match Duration::try_from_secs_f64(secs) {
Ok(v) => v,
Err(e) => crate::panicking::panic(e.description()),
}
}
/// The checked version of [`from_secs_f64`].
///
/// [`from_secs_f64`]: Duration::from_secs_f64
///
/// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
///
/// # Examples
/// ```
/// #![feature(duration_checked_float)]
///
/// use std::time::Duration;
///
/// let dur = Duration::try_from_secs_f64(2.7);
/// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
///
/// let negative = Duration::try_from_secs_f64(-5.0);
/// assert!(negative.is_err());
/// ```
#[unstable(feature = "duration_checked_float", issue = "83400")]
#[inline]
pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromSecsError> {
const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64; const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
let nanos = secs * (NANOS_PER_SEC as f64); let nanos = secs * (NANOS_PER_SEC as f64);
if !nanos.is_finite() { if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration"); Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
} } else if nanos >= MAX_NANOS_F64 {
if nanos >= MAX_NANOS_F64 { Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
panic!("overflow when converting float to duration"); } else if nanos < 0.0 {
} Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
if nanos < 0.0 { } else {
panic!("underflow when converting float to duration"); let nanos = nanos as u128;
} Ok(Duration {
let nanos = nanos as u128; secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
Duration { nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
secs: (nanos / (NANOS_PER_SEC as u128)) as u64, })
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
} }
} }
...@@ -722,21 +748,47 @@ pub const fn from_secs_f64(secs: f64) -> Duration { ...@@ -722,21 +748,47 @@ pub const fn from_secs_f64(secs: f64) -> Duration {
#[inline] #[inline]
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn from_secs_f32(secs: f32) -> Duration { pub const fn from_secs_f32(secs: f32) -> Duration {
match Duration::try_from_secs_f32(secs) {
Ok(v) => v,
Err(e) => crate::panicking::panic(e.description()),
}
}
/// The checked version of [`from_secs_f32`].
///
/// [`from_secs_f32`]: Duration::from_secs_f32
///
/// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
///
/// # Examples
/// ```
/// #![feature(duration_checked_float)]
///
/// use std::time::Duration;
///
/// let dur = Duration::try_from_secs_f32(2.7);
/// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
///
/// let negative = Duration::try_from_secs_f32(-5.0);
/// assert!(negative.is_err());
/// ```
#[unstable(feature = "duration_checked_float", issue = "83400")]
#[inline]
pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromSecsError> {
const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32; const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
let nanos = secs * (NANOS_PER_SEC as f32); let nanos = secs * (NANOS_PER_SEC as f32);
if !nanos.is_finite() { if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration"); Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
} } else if nanos >= MAX_NANOS_F32 {
if nanos >= MAX_NANOS_F32 { Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
panic!("overflow when converting float to duration"); } else if nanos < 0.0 {
} Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
if nanos < 0.0 { } else {
panic!("underflow when converting float to duration"); let nanos = nanos as u128;
} Ok(Duration {
let nanos = nanos as u128; secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
Duration { nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
secs: (nanos / (NANOS_PER_SEC as u128)) as u64, })
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
} }
} }
...@@ -1099,3 +1151,55 @@ fn fmt_decimal( ...@@ -1099,3 +1151,55 @@ fn fmt_decimal(
} }
} }
} }
/// An error which can be returned when converting a floating-point value of seconds
/// into a [`Duration`].
///
/// This error is used as the error type for [`Duration::try_from_secs_f32`] and
/// [`Duration::try_from_secs_f64`].
///
/// # Example
///
/// ```
/// #![feature(duration_checked_float)]
///
/// use std::time::Duration;
///
/// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
/// println!("Failed conversion to Duration: {}", e);
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[unstable(feature = "duration_checked_float", issue = "83400")]
pub struct FromSecsError {
kind: FromSecsErrorKind,
}
impl FromSecsError {
const fn description(&self) -> &'static str {
match self.kind {
FromSecsErrorKind::NonFinite => {
"got non-finite value when converting float to duration"
}
FromSecsErrorKind::Overflow => "overflow when converting float to duration",
FromSecsErrorKind::Underflow => "underflow when converting float to duration",
}
}
}
#[unstable(feature = "duration_checked_float", issue = "83400")]
impl fmt::Display for FromSecsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.description(), f)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum FromSecsErrorKind {
// Value is not a finite value (either infinity or NaN).
NonFinite,
// Value is too large to store in a `Duration`.
Overflow,
// Value is less than `0.0`.
Underflow,
}
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#![feature(const_ptr_read)] #![feature(const_ptr_read)]
#![feature(const_ptr_write)] #![feature(const_ptr_write)]
#![feature(const_ptr_offset)] #![feature(const_ptr_offset)]
#![feature(control_flow_enum)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(core_private_bignum)] #![feature(core_private_bignum)]
#![feature(core_private_diy_float)] #![feature(core_private_diy_float)]
......
...@@ -597,6 +597,9 @@ fn description(&self) -> &str { ...@@ -597,6 +597,9 @@ fn description(&self) -> &str {
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
impl Error for alloc::collections::TryReserveError {} impl Error for alloc::collections::TryReserveError {}
#[unstable(feature = "duration_checked_float", issue = "83400")]
impl Error for core::time::FromSecsError {}
// Copied from `any.rs`. // Copied from `any.rs`.
impl dyn Error + 'static { impl dyn Error + 'static {
/// Returns `true` if the boxed type is the same as `T` /// Returns `true` if the boxed type is the same as `T`
......
...@@ -1092,8 +1092,7 @@ mod move_keyword {} ...@@ -1092,8 +1092,7 @@ mod move_keyword {}
/// Mutable raw pointers work much like mutable references, with the added /// Mutable raw pointers work much like mutable references, with the added
/// possibility of not pointing to a valid object. The syntax is `*mut Type`. /// possibility of not pointing to a valid object. The syntax is `*mut Type`.
/// ///
/// More information on mutable references and pointers can be found in``` /// More information on mutable references and pointers can be found in the [Reference].
/// [Reference].
/// ///
/// [Reference]: ../reference/types/pointer.html#mutable-references-mut /// [Reference]: ../reference/types/pointer.html#mutable-references-mut
mod mut_keyword {} mod mut_keyword {}
......
...@@ -261,6 +261,7 @@ ...@@ -261,6 +261,7 @@
#![feature(doc_masked)] #![feature(doc_masked)]
#![feature(doc_notable_trait)] #![feature(doc_notable_trait)]
#![feature(dropck_eyepatch)] #![feature(dropck_eyepatch)]
#![feature(duration_checked_float)]
#![feature(duration_constants)] #![feature(duration_constants)]
#![feature(edition_panic)] #![feature(edition_panic)]
#![feature(exact_size_is_empty)] #![feature(exact_size_is_empty)]
...@@ -301,7 +302,6 @@ ...@@ -301,7 +302,6 @@
#![feature(panic_internals)] #![feature(panic_internals)]
#![feature(panic_unwind)] #![feature(panic_unwind)]
#![feature(pin_static_ref)] #![feature(pin_static_ref)]
#![feature(prelude_2021)]
#![feature(prelude_import)] #![feature(prelude_import)]
#![feature(ptr_internals)] #![feature(ptr_internals)]
#![feature(raw)] #![feature(raw)]
......
...@@ -25,8 +25,10 @@ ...@@ -25,8 +25,10 @@
//! //!
//! # Prelude contents //! # Prelude contents
//! //!
//! The current version of the prelude (version 1) lives in //! The first version of the prelude is used in Rust 2015 and Rust 2018,
//! [`std::prelude::v1`], and re-exports the following: //! and lives in [`std::prelude::v1`].
//! [`std::prelude::rust_2015`] and [`std::prelude::rust_2018`] re-export this prelude.
//! It re-exports the following:
//! //!
//! * <code>[std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}</code>, //! * <code>[std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}</code>,
//! marker traits that indicate fundamental properties of types. //! marker traits that indicate fundamental properties of types.
...@@ -58,6 +60,12 @@ ...@@ -58,6 +60,12 @@
//! * <code>[std::string]::{[String], [ToString]}</code>, heap-allocated strings. //! * <code>[std::string]::{[String], [ToString]}</code>, heap-allocated strings.
//! * <code>[std::vec]::[Vec]</code>, a growable, heap-allocated vector. //! * <code>[std::vec]::[Vec]</code>, a growable, heap-allocated vector.
//! //!
//! The prelude used in Rust 2021, [`std::prelude::rust_2021`], includes all of the above,
//! and in addition re-exports:
//!
//! * <code>[std::convert]::{[TryFrom], [TryInto]}</code>,
//! * <code>[std::iter]::[FromIterator]</code>.
//!
//! [mem::drop]: crate::mem::drop //! [mem::drop]: crate::mem::drop
//! [std::borrow]: crate::borrow //! [std::borrow]: crate::borrow
//! [std::boxed]: crate::boxed //! [std::boxed]: crate::boxed
...@@ -71,10 +79,16 @@ ...@@ -71,10 +79,16 @@
//! [std::ops]: crate::ops //! [std::ops]: crate::ops
//! [std::option]: crate::option //! [std::option]: crate::option
//! [`std::prelude::v1`]: v1 //! [`std::prelude::v1`]: v1
//! [`std::prelude::rust_2015`]: rust_2015
//! [`std::prelude::rust_2018`]: rust_2018
//! [`std::prelude::rust_2021`]: rust_2021
//! [std::result]: crate::result //! [std::result]: crate::result
//! [std::slice]: crate::slice //! [std::slice]: crate::slice
//! [std::string]: crate::string //! [std::string]: crate::string
//! [std::vec]: mod@crate::vec //! [std::vec]: mod@crate::vec
//! [TryFrom]: crate::convert::TryFrom
//! [TryInto]: crate::convert::TryInto
//! [FromIterator]: crate::iter::FromIterator
//! [`to_owned`]: crate::borrow::ToOwned::to_owned //! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html //! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html //! [book-dtor]: ../../book/ch15-03-drop.html
...@@ -88,9 +102,9 @@ ...@@ -88,9 +102,9 @@
/// The 2015 version of the prelude of The Rust Standard Library. /// The 2015 version of the prelude of The Rust Standard Library.
/// ///
/// See the [module-level documentation](self) for more. /// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2015", issue = "85684")] #[stable(feature = "prelude_2015", since = "1.55.0")]
pub mod rust_2015 { pub mod rust_2015 {
#[unstable(feature = "prelude_2015", issue = "85684")] #[stable(feature = "prelude_2015", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use super::v1::*; pub use super::v1::*;
} }
...@@ -98,9 +112,9 @@ pub mod rust_2015 { ...@@ -98,9 +112,9 @@ pub mod rust_2015 {
/// The 2018 version of the prelude of The Rust Standard Library. /// The 2018 version of the prelude of The Rust Standard Library.
/// ///
/// See the [module-level documentation](self) for more. /// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2018", issue = "85684")] #[stable(feature = "prelude_2018", since = "1.55.0")]
pub mod rust_2018 { pub mod rust_2018 {
#[unstable(feature = "prelude_2018", issue = "85684")] #[stable(feature = "prelude_2018", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use super::v1::*; pub use super::v1::*;
} }
...@@ -108,13 +122,13 @@ pub mod rust_2018 { ...@@ -108,13 +122,13 @@ pub mod rust_2018 {
/// The 2021 version of the prelude of The Rust Standard Library. /// The 2021 version of the prelude of The Rust Standard Library.
/// ///
/// See the [module-level documentation](self) for more. /// See the [module-level documentation](self) for more.
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
pub mod rust_2021 { pub mod rust_2021 {
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use super::v1::*; pub use super::v1::*;
#[unstable(feature = "prelude_2021", issue = "85684")] #[stable(feature = "prelude_2021", since = "1.55.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use core::prelude::rust_2021::*; pub use core::prelude::rust_2021::*;
} }
...@@ -105,6 +105,35 @@ ...@@ -105,6 +105,35 @@
//! }); //! });
//! rx.recv().unwrap(); //! rx.recv().unwrap();
//! ``` //! ```
//!
//! Unbounded receive loop:
//!
//! ```
//! use std::sync::mpsc::sync_channel;
//! use std::thread;
//!
//! let (tx, rx) = sync_channel(3);
//!
//! for _ in 0..3 {
//! // It would be the same without thread and clone here
//! // since there will still be one `tx` left.
//! let tx = tx.clone();
//! // cloned tx dropped within thread
//! thread::spawn(move || tx.send("ok").unwrap());
//! }
//!
//! // Drop the last sender to stop `rx` waiting for message.
//! // The program will not complete if we comment this out.
//! // **All** `tx` needs to be dropped for `rx` to have `Err`.
//! drop(tx);
//!
//! // Unbounded receiver waiting for all senders to complete.
//! while let Ok(msg) = rx.recv() {
//! println!("{}", msg);
//! }
//!
//! println!("completed");
//! ```
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
...@@ -437,6 +466,9 @@ pub struct IntoIter<T> { ...@@ -437,6 +466,9 @@ pub struct IntoIter<T> {
/// ///
/// Messages can be sent through this channel with [`send`]. /// Messages can be sent through this channel with [`send`].
/// ///
/// Note: all senders (the original and the clones) need to be dropped for the receiver
/// to stop blocking to receive messages with [`Receiver::recv`].
///
/// [`send`]: Sender::send /// [`send`]: Sender::send
/// ///
/// # Examples /// # Examples
...@@ -643,7 +675,7 @@ fn inner_unsafe(&self) -> &UnsafeCell<Flavor<T>> { ...@@ -643,7 +675,7 @@ fn inner_unsafe(&self) -> &UnsafeCell<Flavor<T>> {
/// the same order as it was sent, and no [`send`] will block the calling thread /// the same order as it was sent, and no [`send`] will block the calling thread
/// (this channel has an "infinite buffer", unlike [`sync_channel`], which will /// (this channel has an "infinite buffer", unlike [`sync_channel`], which will
/// block after its buffer limit is reached). [`recv`] will block until a message /// block after its buffer limit is reached). [`recv`] will block until a message
/// is available. /// is available while there is at least one [`Sender`] alive (including clones).
/// ///
/// The [`Sender`] can be cloned to [`send`] to the same channel multiple times, but /// The [`Sender`] can be cloned to [`send`] to the same channel multiple times, but
/// only one [`Receiver`] is supported. /// only one [`Receiver`] is supported.
...@@ -806,6 +838,11 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> { ...@@ -806,6 +838,11 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T> Clone for Sender<T> { impl<T> Clone for Sender<T> {
/// Clone a sender to send to other threads.
///
/// Note, be aware of the lifetime of the sender because all senders
/// (including the original) need to be dropped in order for
/// [`Receiver::recv`] to stop blocking.
fn clone(&self) -> Sender<T> { fn clone(&self) -> Sender<T> {
let packet = match *unsafe { self.inner() } { let packet = match *unsafe { self.inner() } {
Flavor::Oneshot(ref p) => { Flavor::Oneshot(ref p) => {
...@@ -1064,9 +1101,10 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> { ...@@ -1064,9 +1101,10 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
/// corresponding channel has hung up. /// corresponding channel has hung up.
/// ///
/// This function will always block the current thread if there is no data /// This function will always block the current thread if there is no data
/// available and it's possible for more data to be sent. Once a message is /// available and it's possible for more data to be sent (at least one sender
/// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this /// still exists). Once a message is sent to the corresponding [`Sender`]
/// receiver will wake up and return that message. /// (or [`SyncSender`]), this receiver will wake up and return that
/// message.
/// ///
/// If the corresponding [`Sender`] has disconnected, or it disconnects while /// If the corresponding [`Sender`] has disconnected, or it disconnects while
/// this call is blocking, this call will wake up and return [`Err`] to /// this call is blocking, this call will wake up and return [`Err`] to
...@@ -1146,9 +1184,10 @@ pub fn recv(&self) -> Result<T, RecvError> { ...@@ -1146,9 +1184,10 @@ pub fn recv(&self) -> Result<T, RecvError> {
/// corresponding channel has hung up, or if it waits more than `timeout`. /// corresponding channel has hung up, or if it waits more than `timeout`.
/// ///
/// This function will always block the current thread if there is no data /// This function will always block the current thread if there is no data
/// available and it's possible for more data to be sent. Once a message is /// available and it's possible for more data to be sent (at least one sender
/// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this /// still exists). Once a message is sent to the corresponding [`Sender`]
/// receiver will wake up and return that message. /// (or [`SyncSender`]), this receiver will wake up and return that
/// message.
/// ///
/// If the corresponding [`Sender`] has disconnected, or it disconnects while /// If the corresponding [`Sender`] has disconnected, or it disconnects while
/// this call is blocking, this call will wake up and return [`Err`] to /// this call is blocking, this call will wake up and return [`Err`] to
......
...@@ -234,6 +234,7 @@ fn clone(&self) -> Self { ...@@ -234,6 +234,7 @@ fn clone(&self) -> Self {
pub const SD_SEND: c_int = 1; pub const SD_SEND: c_int = 1;
pub const SOCK_DGRAM: c_int = 2; pub const SOCK_DGRAM: c_int = 2;
pub const SOCK_STREAM: c_int = 1; pub const SOCK_STREAM: c_int = 1;
pub const SOCKET_ERROR: c_int = -1;
pub const SOL_SOCKET: c_int = 0xffff; pub const SOL_SOCKET: c_int = 0xffff;
pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_RCVTIMEO: c_int = 0x1006;
pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_SNDTIMEO: c_int = 0x1005;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration; use crate::time::Duration;
use libc::{c_int, c_long, c_ulong, c_void}; use libc::{c_int, c_long, c_ulong};
pub type wrlen_t = i32; pub type wrlen_t = i32;
...@@ -93,153 +93,177 @@ pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> ...@@ -93,153 +93,177 @@ pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
impl Socket { impl Socket {
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
let fam = match *addr { let family = match *addr {
SocketAddr::V4(..) => c::AF_INET, SocketAddr::V4(..) => c::AF_INET,
SocketAddr::V6(..) => c::AF_INET6, SocketAddr::V6(..) => c::AF_INET6,
}; };
let socket = unsafe { let socket = unsafe {
match c::WSASocketW( c::WSASocketW(
fam, family,
ty, ty,
0, 0,
ptr::null_mut(), ptr::null_mut(),
0, 0,
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT, c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
) { )
c::INVALID_SOCKET => match c::WSAGetLastError() { };
c::WSAEPROTOTYPE | c::WSAEINVAL => {
match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) if socket != c::INVALID_SOCKET {
{ Ok(Self(socket))
c::INVALID_SOCKET => Err(last_error()), } else {
n => { let error = unsafe { c::WSAGetLastError() };
let s = Socket(n);
s.set_no_inherit()?; if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
Ok(s) return Err(io::Error::from_raw_os_error(error));
} }
}
} let socket =
n => Err(io::Error::from_raw_os_error(n)), unsafe { c::WSASocketW(family, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) };
},
n => Ok(Socket(n)), if socket == c::INVALID_SOCKET {
return Err(last_error());
} }
}?;
Ok(socket) let socket = Self(socket);
socket.set_no_inherit()?;
Ok(socket)
}
} }
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
self.set_nonblocking(true)?; self.set_nonblocking(true)?;
let r = unsafe { let result = {
let (addrp, len) = addr.into_inner(); let (addrp, len) = addr.into_inner();
cvt(c::connect(self.0, addrp, len)) let result = unsafe { c::connect(self.0, addrp, len) };
cvt(result).map(drop)
}; };
self.set_nonblocking(false)?; self.set_nonblocking(false)?;
match r { match result {
Ok(_) => return Ok(()), Err(ref error) if error.kind() == io::ErrorKind::WouldBlock => {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {} if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
Err(e) => return Err(e), return Err(io::Error::new_const(
} io::ErrorKind::InvalidInput,
&"cannot set a 0 duration timeout",
if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { ));
return Err(io::Error::new_const( }
io::ErrorKind::InvalidInput,
&"cannot set a 0 duration timeout",
));
}
let mut timeout = c::timeval {
tv_sec: timeout.as_secs() as c_long,
tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
};
if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
timeout.tv_usec = 1;
}
let fds = unsafe { let mut timeout = c::timeval {
let mut fds = mem::zeroed::<c::fd_set>(); tv_sec: timeout.as_secs() as c_long,
fds.fd_count = 1; tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
fds.fd_array[0] = self.0; };
fds
};
let mut writefds = fds; if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
let mut errorfds = fds; timeout.tv_usec = 1;
}
let n = let fds = {
unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? }; let mut fds = unsafe { mem::zeroed::<c::fd_set>() };
fds.fd_count = 1;
fds.fd_array[0] = self.0;
fds
};
let mut writefds = fds;
let mut errorfds = fds;
let count = {
let result = unsafe {
c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout)
};
cvt(result)?
};
match count {
0 => {
Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out"))
}
_ => {
if writefds.fd_count != 1 {
if let Some(e) = self.take_error()? {
return Err(e);
}
}
match n { Ok(())
0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")),
_ => {
if writefds.fd_count != 1 {
if let Some(e) = self.take_error()? {
return Err(e);
} }
} }
Ok(())
} }
_ => result,
} }
} }
pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result<Socket> { pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result<Socket> {
let socket = unsafe { let socket = unsafe { c::accept(self.0, storage, len) };
match c::accept(self.0, storage, len) {
c::INVALID_SOCKET => Err(last_error()), match socket {
n => Ok(Socket(n)), c::INVALID_SOCKET => Err(last_error()),
} _ => Ok(Self(socket)),
}?; }
Ok(socket)
} }
pub fn duplicate(&self) -> io::Result<Socket> { pub fn duplicate(&self) -> io::Result<Socket> {
let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
let result = unsafe { c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info) };
cvt(result)?;
let socket = unsafe { let socket = unsafe {
let mut info: c::WSAPROTOCOL_INFO = mem::zeroed(); c::WSASocketW(
cvt(c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info))?;
match c::WSASocketW(
info.iAddressFamily, info.iAddressFamily,
info.iSocketType, info.iSocketType,
info.iProtocol, info.iProtocol,
&mut info, &mut info,
0, 0,
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT, c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
) { )
c::INVALID_SOCKET => match c::WSAGetLastError() { };
c::WSAEPROTOTYPE | c::WSAEINVAL => {
match c::WSASocketW( if socket != c::INVALID_SOCKET {
info.iAddressFamily, Ok(Self(socket))
info.iSocketType, } else {
info.iProtocol, let error = unsafe { c::WSAGetLastError() };
&mut info,
0, if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
c::WSA_FLAG_OVERLAPPED, return Err(io::Error::from_raw_os_error(error));
) { }
c::INVALID_SOCKET => Err(last_error()),
n => { let socket = unsafe {
let s = Socket(n); c::WSASocketW(
s.set_no_inherit()?; info.iAddressFamily,
Ok(s) info.iSocketType,
} info.iProtocol,
} &mut info,
} 0,
n => Err(io::Error::from_raw_os_error(n)), c::WSA_FLAG_OVERLAPPED,
}, )
n => Ok(Socket(n)), };
if socket == c::INVALID_SOCKET {
return Err(last_error());
} }
}?;
Ok(socket) let socket = Self(socket);
socket.set_no_inherit()?;
Ok(socket)
}
} }
fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
// On unix when a socket is shut down all further reads return 0, so we // On unix when a socket is shut down all further reads return 0, so we
// do the same on windows to map a shut down socket to returning EOF. // do the same on windows to map a shut down socket to returning EOF.
let len = cmp::min(buf.len(), i32::MAX as usize) as i32; let length = cmp::min(buf.len(), i32::MAX as usize) as i32;
unsafe { let result = unsafe { c::recv(self.0, buf.as_mut_ptr() as *mut _, length, flags) };
match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) {
-1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), match result {
-1 => Err(last_error()), c::SOCKET_ERROR => {
n => Ok(n as usize), let error = unsafe { c::WSAGetLastError() };
if error == c::WSAESHUTDOWN {
Ok(0)
} else {
Err(io::Error::from_raw_os_error(error))
}
} }
_ => Ok(result as usize),
} }
} }
...@@ -250,23 +274,31 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { ...@@ -250,23 +274,31 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
// On unix when a socket is shut down all further reads return 0, so we // On unix when a socket is shut down all further reads return 0, so we
// do the same on windows to map a shut down socket to returning EOF. // do the same on windows to map a shut down socket to returning EOF.
let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD; let length = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
let mut nread = 0; let mut nread = 0;
let mut flags = 0; let mut flags = 0;
unsafe { let result = unsafe {
let ret = c::WSARecv( c::WSARecv(
self.0, self.0,
bufs.as_mut_ptr() as *mut c::WSABUF, bufs.as_mut_ptr() as *mut c::WSABUF,
len, length,
&mut nread, &mut nread,
&mut flags, &mut flags,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
); )
match ret { };
0 => Ok(nread as usize),
_ if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), match result {
_ => Err(last_error()), 0 => Ok(nread as usize),
_ => {
let error = unsafe { c::WSAGetLastError() };
if error == c::WSAESHUTDOWN {
Ok(0)
} else {
Err(io::Error::from_raw_os_error(error))
}
} }
} }
} }
...@@ -285,27 +317,34 @@ fn recv_from_with_flags( ...@@ -285,27 +317,34 @@ fn recv_from_with_flags(
buf: &mut [u8], buf: &mut [u8],
flags: c_int, flags: c_int,
) -> io::Result<(usize, SocketAddr)> { ) -> io::Result<(usize, SocketAddr)> {
let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() }; let mut storage = unsafe { mem::zeroed::<c::SOCKADDR_STORAGE_LH>() };
let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t; let length = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
// On unix when a socket is shut down all further reads return 0, so we // On unix when a socket is shut down all further reads return 0, so we
// do the same on windows to map a shut down socket to returning EOF. // do the same on windows to map a shut down socket to returning EOF.
unsafe { let result = unsafe {
match c::recvfrom( c::recvfrom(
self.0, self.0,
buf.as_mut_ptr() as *mut c_void, buf.as_mut_ptr() as *mut _,
len, length,
flags, flags,
&mut storage as *mut _ as *mut _, &mut storage as *mut _ as *mut _,
&mut addrlen, &mut addrlen,
) { )
-1 if c::WSAGetLastError() == c::WSAESHUTDOWN => { };
match result {
c::SOCKET_ERROR => {
let error = unsafe { c::WSAGetLastError() };
if error == c::WSAESHUTDOWN {
Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?)) Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?))
} else {
Err(io::Error::from_raw_os_error(error))
} }
-1 => Err(last_error()),
n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)),
} }
_ => Ok((result as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)),
} }
} }
...@@ -318,20 +357,20 @@ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { ...@@ -318,20 +357,20 @@ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
} }
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD; let length = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
let mut nwritten = 0; let mut nwritten = 0;
unsafe { let result = unsafe {
cvt(c::WSASend( c::WSASend(
self.0, self.0,
bufs.as_ptr() as *const c::WSABUF as *mut c::WSABUF, bufs.as_ptr() as *const c::WSABUF as *mut _,
len, length,
&mut nwritten, &mut nwritten,
0, 0,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
))?; )
} };
Ok(nwritten as usize) cvt(result).map(|_| nwritten as usize)
} }
#[inline] #[inline]
...@@ -384,14 +423,14 @@ pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { ...@@ -384,14 +423,14 @@ pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
Shutdown::Read => c::SD_RECEIVE, Shutdown::Read => c::SD_RECEIVE,
Shutdown::Both => c::SD_BOTH, Shutdown::Both => c::SD_BOTH,
}; };
cvt(unsafe { c::shutdown(self.0, how) })?; let result = unsafe { c::shutdown(self.0, how) };
Ok(()) cvt(result).map(drop)
} }
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as c_ulong; let mut nonblocking = nonblocking as c_ulong;
let r = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) }; let result = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
if r == 0 { Ok(()) } else { Err(io::Error::last_os_error()) } cvt(result).map(drop)
} }
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
......
...@@ -965,14 +965,8 @@ fn method( ...@@ -965,14 +965,8 @@ fn method(
} }
} }
const ALLOWED_ATTRIBUTES: &[Symbol] = &[ const ALLOWED_ATTRIBUTES: &[Symbol] =
sym::export_name, &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive];
sym::link_section,
sym::must_use,
sym::no_mangle,
sym::repr,
sym::non_exhaustive,
];
fn attributes(it: &clean::Item) -> Vec<String> { fn attributes(it: &clean::Item) -> Vec<String> {
it.attrs it.attrs
......
...@@ -8,14 +8,6 @@ pub extern "C" fn f() {} ...@@ -8,14 +8,6 @@ pub extern "C" fn f() {}
#[export_name = "bar"] #[export_name = "bar"]
pub extern "C" fn g() {} pub extern "C" fn g() {}
// @matches foo/enum.Foo.html '//*[@class="rust enum"]' \
// '#\[repr\(i64\)\]\n#\[must_use\]'
#[repr(i64)]
#[must_use]
pub enum Foo {
Bar,
}
// @has foo/struct.Repr.html '//*[@class="docblock type-decl"]' '#[repr(C, align(8))]' // @has foo/struct.Repr.html '//*[@class="docblock type-decl"]' '#[repr(C, align(8))]'
#[repr(C, align(8))] #[repr(C, align(8))]
pub struct Repr; pub struct Repr;
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
// therefore should not concern itself with the lints. // therefore should not concern itself with the lints.
#[deny(warnings)] #[deny(warnings)]
// @has cap_lints/struct.Foo.html //pre '#[must_use]' // @has cap_lints/struct.Foo.html //* 'Struct Foo'
#[must_use]
pub struct Foo { pub struct Foo {
field: i32, field: i32,
} }
// @has must_use/struct.Struct.html //pre '#[must_use]'
#[must_use]
pub struct Struct {
field: i32,
}
// @has must_use/enum.Enum.html //pre '#[must_use = "message"]'
#[must_use = "message"]
pub enum Enum {
Variant(i32),
}
#![crate_name = "foo"]
pub trait Foo {
// @has foo/trait.Foo.html '//div[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]'
#[must_use]
fn foo();
}
#[must_use]
pub struct Bar;
impl Bar {
// @has foo/struct.Bar.html '//div[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]'
#[must_use]
pub fn bar() {}
// @has foo/struct.Bar.html '//div[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]'
#[must_use]
pub fn bar2() {}
}
Subproject commit 13da28cc2bc1b59f7af817eca36927a71edb023c Subproject commit f0618a8f06a464840079f30b3e25bcdcca3922a3
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册