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
This commit is contained in:
commit
607d6b00d4
25 changed files with 499 additions and 259 deletions
2
.mailmap
2
.mailmap
|
@ -166,6 +166,8 @@ lcnr <bastian_kauschke@hotmail.de>
|
|||
Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <lee@leejeffery.co.uk>
|
||||
Lee Wondong <wdlee91@gmail.com>
|
||||
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>
|
||||
Lindsey Kuper <lindsey@composition.al> <lindsey@rockstargirl.org>
|
||||
Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com>
|
||||
|
|
|
@ -331,7 +331,7 @@ pub fn lower_crate<'a, 'hir>(
|
|||
lifetimes_to_define: Vec::new(),
|
||||
is_collecting_in_band_lifetimes: false,
|
||||
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()),
|
||||
}
|
||||
.lower_crate(krate)
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(format_args_capture)]
|
||||
#![feature(iter_zip)]
|
||||
|
|
|
@ -416,7 +416,6 @@ symbols! {
|
|||
constructor,
|
||||
contents,
|
||||
context,
|
||||
control_flow_enum,
|
||||
convert,
|
||||
copy,
|
||||
copy_closures,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -1959,6 +1959,31 @@ pub trait Iterator {
|
|||
/// assert_eq!(it.len(), 2);
|
||||
/// 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]
|
||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
|
@ -2001,6 +2026,22 @@ pub trait Iterator {
|
|||
/// // It short-circuited, so the remaining items are still in the iterator:
|
||||
/// 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]
|
||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
||||
fn try_for_each<F, R>(&mut self, f: F) -> R
|
||||
|
|
|
@ -402,10 +402,60 @@ impl<T> MaybeUninit<T> {
|
|||
u
|
||||
}
|
||||
|
||||
/// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
|
||||
/// 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
|
||||
/// reference to the (now safely initialized) contents of `self`.
|
||||
/// Sets the value of the `MaybeUninit<T>`.
|
||||
///
|
||||
/// This overwrites any previous value 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 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")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
|
||||
#[inline(always)]
|
||||
|
@ -564,9 +614,11 @@ impl<T> MaybeUninit<T> {
|
|||
/// behavior. The [type-level documentation][inv] contains more information about
|
||||
/// this initialization invariant.
|
||||
///
|
||||
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. 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
|
||||
/// Moreover, similar to the [`ptr::read`] function, this function creates a
|
||||
/// bitwise copy of the contents, regardless whether the contained type
|
||||
/// 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.
|
||||
///
|
||||
/// [inv]: #initialization-invariant
|
||||
|
@ -622,7 +674,8 @@ impl<T> MaybeUninit<T> {
|
|||
|
||||
/// 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
|
||||
///
|
||||
|
@ -632,11 +685,12 @@ impl<T> MaybeUninit<T> {
|
|||
///
|
||||
/// On top of that, all additional invariants of the type `T` must be
|
||||
/// satisfied, as the `Drop` implementation of `T` (or its members) may
|
||||
/// rely on this. For example, a `1`-initialized [`Vec<T>`] is considered
|
||||
/// initialized (under the current implementation; this does not constitute
|
||||
/// a stable guarantee) because the only requirement the compiler knows
|
||||
/// about it is that the data pointer must be non-null. Dropping such a
|
||||
/// `Vec<T>` however will cause undefined behaviour.
|
||||
/// rely on this. For example, setting a [`Vec<T>`] to an invalid but
|
||||
/// non-null address makes it initialized (under the current implementation;
|
||||
/// this does not constitute a stable guarantee), because the only
|
||||
/// requirement the compiler knows about it is that the data pointer must be
|
||||
/// non-null. Dropping such a `Vec<T>` however will cause undefined
|
||||
/// behaviour.
|
||||
///
|
||||
/// [`assume_init`]: MaybeUninit::assume_init
|
||||
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::{convert, ops};
|
|||
///
|
||||
/// Early-exiting from [`Iterator::try_for_each`]:
|
||||
/// ```
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// let r = (2..100).try_for_each(|x| {
|
||||
|
@ -26,7 +25,6 @@ use crate::{convert, ops};
|
|||
///
|
||||
/// A basic tree traversal:
|
||||
/// ```no_run
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::ControlFlow;
|
||||
///
|
||||
/// pub struct TreeNode<T> {
|
||||
|
@ -48,13 +46,15 @@ use crate::{convert, ops};
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[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)]
|
||||
pub enum ControlFlow<B, C = ()> {
|
||||
/// 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")]
|
||||
Continue(C),
|
||||
/// Exit the operation without running subsequent phases.
|
||||
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
|
||||
#[cfg_attr(not(bootstrap), lang = "Break")]
|
||||
Break(B),
|
||||
// Yes, the order of the variants doesn't match the type parameters.
|
||||
|
|
|
@ -55,7 +55,6 @@ use crate::ops::ControlFlow;
|
|||
/// into the return type using [`Try::from_output`]:
|
||||
/// ```
|
||||
/// # #![feature(try_trait_v2)]
|
||||
/// # #![feature(control_flow_enum)]
|
||||
/// # use std::ops::{ControlFlow, Try};
|
||||
/// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
|
||||
/// iter: impl Iterator<Item = T>,
|
||||
|
@ -79,7 +78,6 @@ use crate::ops::ControlFlow;
|
|||
/// recreated from their corresponding residual, so we'll just call it:
|
||||
/// ```
|
||||
/// # #![feature(try_trait_v2)]
|
||||
/// # #![feature(control_flow_enum)]
|
||||
/// # use std::ops::{ControlFlow, Try};
|
||||
/// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
|
||||
/// iter: impl Iterator<Item = T>,
|
||||
|
@ -170,7 +168,6 @@ pub trait Try: FromResidual {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(try_trait_v2)]
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::Try;
|
||||
///
|
||||
/// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
|
||||
|
@ -202,7 +199,6 @@ pub trait Try: FromResidual {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(try_trait_v2)]
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::{ControlFlow, Try};
|
||||
///
|
||||
/// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
|
||||
|
@ -329,7 +325,6 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(try_trait_v2)]
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// use std::ops::{ControlFlow, FromResidual};
|
||||
///
|
||||
/// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
|
||||
|
|
|
@ -11,9 +11,9 @@ pub mod v1;
|
|||
/// The 2015 version of the core prelude.
|
||||
///
|
||||
/// 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 {
|
||||
#[unstable(feature = "prelude_2015", issue = "85684")]
|
||||
#[stable(feature = "prelude_2015", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use super::v1::*;
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ pub mod rust_2015 {
|
|||
/// The 2018 version of the core prelude.
|
||||
///
|
||||
/// 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 {
|
||||
#[unstable(feature = "prelude_2018", issue = "85684")]
|
||||
#[stable(feature = "prelude_2018", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use super::v1::*;
|
||||
}
|
||||
|
@ -31,17 +31,17 @@ pub mod rust_2018 {
|
|||
/// The 2021 version of the core prelude.
|
||||
///
|
||||
/// 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 {
|
||||
#[unstable(feature = "prelude_2021", issue = "85684")]
|
||||
#[stable(feature = "prelude_2021", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use super::v1::*;
|
||||
|
||||
#[unstable(feature = "prelude_2021", issue = "85684")]
|
||||
#[stable(feature = "prelude_2021", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::iter::FromIterator;
|
||||
|
||||
#[unstable(feature = "prelude_2021", issue = "85684")]
|
||||
#[stable(feature = "prelude_2021", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::convert::{TryFrom, TryInto};
|
||||
}
|
||||
|
|
|
@ -687,21 +687,47 @@ impl Duration {
|
|||
#[inline]
|
||||
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
|
||||
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;
|
||||
let nanos = secs * (NANOS_PER_SEC as f64);
|
||||
if !nanos.is_finite() {
|
||||
panic!("got non-finite value when converting float to duration");
|
||||
}
|
||||
if nanos >= MAX_NANOS_F64 {
|
||||
panic!("overflow when converting float to duration");
|
||||
}
|
||||
if nanos < 0.0 {
|
||||
panic!("underflow when converting float to duration");
|
||||
}
|
||||
let nanos = nanos as u128;
|
||||
Duration {
|
||||
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
|
||||
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
|
||||
} else if nanos >= MAX_NANOS_F64 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
|
||||
} else if nanos < 0.0 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
|
||||
} else {
|
||||
let nanos = nanos as u128;
|
||||
Ok(Duration {
|
||||
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
|
||||
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -722,21 +748,47 @@ impl Duration {
|
|||
#[inline]
|
||||
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
|
||||
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;
|
||||
let nanos = secs * (NANOS_PER_SEC as f32);
|
||||
if !nanos.is_finite() {
|
||||
panic!("got non-finite value when converting float to duration");
|
||||
}
|
||||
if nanos >= MAX_NANOS_F32 {
|
||||
panic!("overflow when converting float to duration");
|
||||
}
|
||||
if nanos < 0.0 {
|
||||
panic!("underflow when converting float to duration");
|
||||
}
|
||||
let nanos = nanos as u128;
|
||||
Duration {
|
||||
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
|
||||
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
|
||||
} else if nanos >= MAX_NANOS_F32 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
|
||||
} else if nanos < 0.0 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
|
||||
} else {
|
||||
let nanos = nanos as u128;
|
||||
Ok(Duration {
|
||||
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
|
||||
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1099,3 +1151,55 @@ impl fmt::Debug for Duration {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 @@
|
|||
#![feature(const_ptr_read)]
|
||||
#![feature(const_ptr_write)]
|
||||
#![feature(const_ptr_offset)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
|
|
|
@ -597,6 +597,9 @@ impl Error for char::ParseCharError {
|
|||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
impl Error for alloc::collections::TryReserveError {}
|
||||
|
||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||
impl Error for core::time::FromSecsError {}
|
||||
|
||||
// Copied from `any.rs`.
|
||||
impl dyn Error + 'static {
|
||||
/// Returns `true` if the boxed type is the same as `T`
|
||||
|
|
|
@ -1092,8 +1092,7 @@ mod move_keyword {}
|
|||
/// Mutable raw pointers work much like mutable references, with the added
|
||||
/// possibility of not pointing to a valid object. The syntax is `*mut Type`.
|
||||
///
|
||||
/// More information on mutable references and pointers can be found in```
|
||||
/// [Reference].
|
||||
/// More information on mutable references and pointers can be found in the [Reference].
|
||||
///
|
||||
/// [Reference]: ../reference/types/pointer.html#mutable-references-mut
|
||||
mod mut_keyword {}
|
||||
|
|
|
@ -261,6 +261,7 @@
|
|||
#![feature(doc_masked)]
|
||||
#![feature(doc_notable_trait)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(duration_checked_float)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(edition_panic)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
|
@ -301,7 +302,6 @@
|
|||
#![feature(panic_internals)]
|
||||
#![feature(panic_unwind)]
|
||||
#![feature(pin_static_ref)]
|
||||
#![feature(prelude_2021)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(raw)]
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
//!
|
||||
//! # Prelude contents
|
||||
//!
|
||||
//! The current version of the prelude (version 1) lives in
|
||||
//! [`std::prelude::v1`], and re-exports the following:
|
||||
//! The first version of the prelude is used in Rust 2015 and Rust 2018,
|
||||
//! 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>,
|
||||
//! marker traits that indicate fundamental properties of types.
|
||||
|
@ -58,6 +60,12 @@
|
|||
//! * <code>[std::string]::{[String], [ToString]}</code>, heap-allocated strings.
|
||||
//! * <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
|
||||
//! [std::borrow]: crate::borrow
|
||||
//! [std::boxed]: crate::boxed
|
||||
|
@ -71,10 +79,16 @@
|
|||
//! [std::ops]: crate::ops
|
||||
//! [std::option]: crate::option
|
||||
//! [`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::slice]: crate::slice
|
||||
//! [std::string]: crate::string
|
||||
//! [std::vec]: mod@crate::vec
|
||||
//! [TryFrom]: crate::convert::TryFrom
|
||||
//! [TryInto]: crate::convert::TryInto
|
||||
//! [FromIterator]: crate::iter::FromIterator
|
||||
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
|
||||
//! [book-closures]: ../../book/ch13-01-closures.html
|
||||
//! [book-dtor]: ../../book/ch15-03-drop.html
|
||||
|
@ -88,9 +102,9 @@ pub mod v1;
|
|||
/// The 2015 version of the prelude of The Rust Standard Library.
|
||||
///
|
||||
/// 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 {
|
||||
#[unstable(feature = "prelude_2015", issue = "85684")]
|
||||
#[stable(feature = "prelude_2015", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use super::v1::*;
|
||||
}
|
||||
|
@ -98,9 +112,9 @@ pub mod rust_2015 {
|
|||
/// The 2018 version of the prelude of The Rust Standard Library.
|
||||
///
|
||||
/// 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 {
|
||||
#[unstable(feature = "prelude_2018", issue = "85684")]
|
||||
#[stable(feature = "prelude_2018", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use super::v1::*;
|
||||
}
|
||||
|
@ -108,13 +122,13 @@ pub mod rust_2018 {
|
|||
/// The 2021 version of the prelude of The Rust Standard Library.
|
||||
///
|
||||
/// 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 {
|
||||
#[unstable(feature = "prelude_2021", issue = "85684")]
|
||||
#[stable(feature = "prelude_2021", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use super::v1::*;
|
||||
|
||||
#[unstable(feature = "prelude_2021", issue = "85684")]
|
||||
#[stable(feature = "prelude_2021", since = "1.55.0")]
|
||||
#[doc(no_inline)]
|
||||
pub use core::prelude::rust_2021::*;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,35 @@
|
|||
//! });
|
||||
//! 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")]
|
||||
|
||||
|
@ -437,6 +466,9 @@ pub struct IntoIter<T> {
|
|||
///
|
||||
/// 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
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -643,7 +675,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
|
|||
/// 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
|
||||
/// 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
|
||||
/// only one [`Receiver`] is supported.
|
||||
|
@ -806,6 +838,11 @@ impl<T> Sender<T> {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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> {
|
||||
let packet = match *unsafe { self.inner() } {
|
||||
Flavor::Oneshot(ref p) => {
|
||||
|
@ -1064,9 +1101,10 @@ impl<T> Receiver<T> {
|
|||
/// corresponding channel has hung up.
|
||||
///
|
||||
/// 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
|
||||
/// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
|
||||
/// receiver will wake up and return that message.
|
||||
/// available and it's possible for more data to be sent (at least one sender
|
||||
/// still exists). Once a message is sent to the corresponding [`Sender`]
|
||||
/// (or [`SyncSender`]), this receiver will wake up and return that
|
||||
/// message.
|
||||
///
|
||||
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
|
||||
/// this call is blocking, this call will wake up and return [`Err`] to
|
||||
|
@ -1146,9 +1184,10 @@ impl<T> Receiver<T> {
|
|||
/// 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
|
||||
/// available and it's possible for more data to be sent. Once a message is
|
||||
/// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this
|
||||
/// receiver will wake up and return that message.
|
||||
/// available and it's possible for more data to be sent (at least one sender
|
||||
/// still exists). Once a message is sent to the corresponding [`Sender`]
|
||||
/// (or [`SyncSender`]), this receiver will wake up and return that
|
||||
/// message.
|
||||
///
|
||||
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
|
||||
/// this call is blocking, this call will wake up and return [`Err`] to
|
||||
|
|
|
@ -234,6 +234,7 @@ pub const SD_RECEIVE: c_int = 0;
|
|||
pub const SD_SEND: c_int = 1;
|
||||
pub const SOCK_DGRAM: c_int = 2;
|
||||
pub const SOCK_STREAM: c_int = 1;
|
||||
pub const SOCKET_ERROR: c_int = -1;
|
||||
pub const SOL_SOCKET: c_int = 0xffff;
|
||||
pub const SO_RCVTIMEO: c_int = 0x1006;
|
||||
pub const SO_SNDTIMEO: c_int = 0x1005;
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::sys_common::net;
|
|||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
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;
|
||||
|
||||
|
@ -93,153 +93,177 @@ where
|
|||
|
||||
impl 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::V6(..) => c::AF_INET6,
|
||||
};
|
||||
let socket = unsafe {
|
||||
match c::WSASocketW(
|
||||
fam,
|
||||
c::WSASocketW(
|
||||
family,
|
||||
ty,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
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)
|
||||
{
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
n => {
|
||||
let s = Socket(n);
|
||||
s.set_no_inherit()?;
|
||||
Ok(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
n => Err(io::Error::from_raw_os_error(n)),
|
||||
},
|
||||
n => Ok(Socket(n)),
|
||||
)
|
||||
};
|
||||
|
||||
if socket != c::INVALID_SOCKET {
|
||||
Ok(Self(socket))
|
||||
} else {
|
||||
let error = unsafe { c::WSAGetLastError() };
|
||||
|
||||
if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
|
||||
return Err(io::Error::from_raw_os_error(error));
|
||||
}
|
||||
}?;
|
||||
Ok(socket)
|
||||
|
||||
let socket =
|
||||
unsafe { c::WSASocketW(family, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) };
|
||||
|
||||
if socket == c::INVALID_SOCKET {
|
||||
return Err(last_error());
|
||||
}
|
||||
|
||||
let socket = Self(socket);
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
|
||||
self.set_nonblocking(true)?;
|
||||
let r = unsafe {
|
||||
let result = {
|
||||
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)?;
|
||||
|
||||
match r {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
match result {
|
||||
Err(ref error) if error.kind() == io::ErrorKind::WouldBlock => {
|
||||
if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
|
||||
timeout.tv_usec = 1;
|
||||
}
|
||||
|
||||
let fds = unsafe {
|
||||
let mut fds = mem::zeroed::<c::fd_set>();
|
||||
fds.fd_count = 1;
|
||||
fds.fd_array[0] = self.0;
|
||||
fds
|
||||
};
|
||||
let fds = {
|
||||
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 mut writefds = fds;
|
||||
let mut errorfds = fds;
|
||||
|
||||
let n =
|
||||
unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? };
|
||||
let count = {
|
||||
let result = unsafe {
|
||||
c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout)
|
||||
};
|
||||
cvt(result)?
|
||||
};
|
||||
|
||||
match n {
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => result,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result<Socket> {
|
||||
let socket = unsafe {
|
||||
match c::accept(self.0, storage, len) {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
n => Ok(Socket(n)),
|
||||
}
|
||||
}?;
|
||||
Ok(socket)
|
||||
let socket = unsafe { c::accept(self.0, storage, len) };
|
||||
|
||||
match socket {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
_ => Ok(Self(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 mut info: c::WSAPROTOCOL_INFO = mem::zeroed();
|
||||
cvt(c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info))?;
|
||||
|
||||
match c::WSASocketW(
|
||||
c::WSASocketW(
|
||||
info.iAddressFamily,
|
||||
info.iSocketType,
|
||||
info.iProtocol,
|
||||
&mut info,
|
||||
0,
|
||||
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
|
||||
) {
|
||||
c::INVALID_SOCKET => match c::WSAGetLastError() {
|
||||
c::WSAEPROTOTYPE | c::WSAEINVAL => {
|
||||
match c::WSASocketW(
|
||||
info.iAddressFamily,
|
||||
info.iSocketType,
|
||||
info.iProtocol,
|
||||
&mut info,
|
||||
0,
|
||||
c::WSA_FLAG_OVERLAPPED,
|
||||
) {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
n => {
|
||||
let s = Socket(n);
|
||||
s.set_no_inherit()?;
|
||||
Ok(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
n => Err(io::Error::from_raw_os_error(n)),
|
||||
},
|
||||
n => Ok(Socket(n)),
|
||||
)
|
||||
};
|
||||
|
||||
if socket != c::INVALID_SOCKET {
|
||||
Ok(Self(socket))
|
||||
} else {
|
||||
let error = unsafe { c::WSAGetLastError() };
|
||||
|
||||
if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
|
||||
return Err(io::Error::from_raw_os_error(error));
|
||||
}
|
||||
}?;
|
||||
Ok(socket)
|
||||
|
||||
let socket = unsafe {
|
||||
c::WSASocketW(
|
||||
info.iAddressFamily,
|
||||
info.iSocketType,
|
||||
info.iProtocol,
|
||||
&mut info,
|
||||
0,
|
||||
c::WSA_FLAG_OVERLAPPED,
|
||||
)
|
||||
};
|
||||
|
||||
if socket == c::INVALID_SOCKET {
|
||||
return Err(last_error());
|
||||
}
|
||||
|
||||
let socket = Self(socket);
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// 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;
|
||||
unsafe {
|
||||
match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) {
|
||||
-1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
|
||||
-1 => Err(last_error()),
|
||||
n => Ok(n as usize),
|
||||
let length = cmp::min(buf.len(), i32::MAX as usize) as i32;
|
||||
let result = unsafe { c::recv(self.0, buf.as_mut_ptr() as *mut _, length, flags) };
|
||||
|
||||
match result {
|
||||
c::SOCKET_ERROR => {
|
||||
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 @@ impl Socket {
|
|||
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
|
||||
// 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 flags = 0;
|
||||
unsafe {
|
||||
let ret = c::WSARecv(
|
||||
let result = unsafe {
|
||||
c::WSARecv(
|
||||
self.0,
|
||||
bufs.as_mut_ptr() as *mut c::WSABUF,
|
||||
len,
|
||||
length,
|
||||
&mut nread,
|
||||
&mut flags,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
);
|
||||
match ret {
|
||||
0 => Ok(nread as usize),
|
||||
_ if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
|
||||
_ => Err(last_error()),
|
||||
)
|
||||
};
|
||||
|
||||
match result {
|
||||
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 @@ impl Socket {
|
|||
buf: &mut [u8],
|
||||
flags: c_int,
|
||||
) -> 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 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
|
||||
// do the same on windows to map a shut down socket to returning EOF.
|
||||
unsafe {
|
||||
match c::recvfrom(
|
||||
let result = unsafe {
|
||||
c::recvfrom(
|
||||
self.0,
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
len,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
length,
|
||||
flags,
|
||||
&mut storage as *mut _ as *mut _,
|
||||
&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)?))
|
||||
} 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 @@ impl Socket {
|
|||
}
|
||||
|
||||
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;
|
||||
unsafe {
|
||||
cvt(c::WSASend(
|
||||
let result = unsafe {
|
||||
c::WSASend(
|
||||
self.0,
|
||||
bufs.as_ptr() as *const c::WSABUF as *mut c::WSABUF,
|
||||
len,
|
||||
bufs.as_ptr() as *const c::WSABUF as *mut _,
|
||||
length,
|
||||
&mut nwritten,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
}
|
||||
Ok(nwritten as usize)
|
||||
)
|
||||
};
|
||||
cvt(result).map(|_| nwritten as usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -384,14 +423,14 @@ impl Socket {
|
|||
Shutdown::Read => c::SD_RECEIVE,
|
||||
Shutdown::Both => c::SD_BOTH,
|
||||
};
|
||||
cvt(unsafe { c::shutdown(self.0, how) })?;
|
||||
Ok(())
|
||||
let result = unsafe { c::shutdown(self.0, how) };
|
||||
cvt(result).map(drop)
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
let mut nonblocking = nonblocking as c_ulong;
|
||||
let r = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
|
||||
if r == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }
|
||||
let result = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
|
||||
cvt(result).map(drop)
|
||||
}
|
||||
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||
|
|
|
@ -965,14 +965,8 @@ fn render_assoc_item(
|
|||
}
|
||||
}
|
||||
|
||||
const ALLOWED_ATTRIBUTES: &[Symbol] = &[
|
||||
sym::export_name,
|
||||
sym::link_section,
|
||||
sym::must_use,
|
||||
sym::no_mangle,
|
||||
sym::repr,
|
||||
sym::non_exhaustive,
|
||||
];
|
||||
const ALLOWED_ATTRIBUTES: &[Symbol] =
|
||||
&[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive];
|
||||
|
||||
fn attributes(it: &clean::Item) -> Vec<String> {
|
||||
it.attrs
|
||||
|
|
|
@ -8,14 +8,6 @@ pub extern "C" fn f() {}
|
|||
#[export_name = "bar"]
|
||||
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))]'
|
||||
#[repr(C, align(8))]
|
||||
pub struct Repr;
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
// therefore should not concern itself with the lints.
|
||||
#[deny(warnings)]
|
||||
|
||||
// @has cap_lints/struct.Foo.html //pre '#[must_use]'
|
||||
#[must_use]
|
||||
// @has cap_lints/struct.Foo.html //* 'Struct Foo'
|
||||
pub struct Foo {
|
||||
field: i32,
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// @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),
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#![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() {}
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit 13da28cc2bc1b59f7af817eca36927a71edb023c
|
||||
Subproject commit f0618a8f06a464840079f30b3e25bcdcca3922a3
|
Loading…
Add table
Reference in a new issue