Auto merge of #76265 - Dylan-DPC:rollup-j3i509l, r=Dylan-DPC

Rollup of 12 pull requests

Successful merges:

 - #75150 (Add a note for Ipv4Addr::to_ipv6_compatible)
 - #76120 (Add `[T; N]::as_[mut_]slice`)
 - #76142 (Make all methods of `std::net::Ipv4Addr` const)
 - #76164 (Link to slice pattern in array docs)
 - #76167 (Replace MinGW library hack with heuristic controlling link mode)
 - #76204 (Rename and expose LoopState as ControlFlow)
 - #76238 (Move to intra-doc links for library/core/src/iter/traits/iterator.rs)
 - #76242 (Read: adjust a FIXME reference)
 - #76243 (Fix typos in vec try_reserve(_exact) docs)
 - #76245 (inliner: Avoid query cycles when optimizing generators)
 - #76255 (Update books)
 - #76261 (Use intra-doc links in `core::marker`)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-09-03 00:24:50 +00:00
commit 4f66117945
25 changed files with 365 additions and 304 deletions

View file

@ -1014,86 +1014,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
}
}
// Because windows-gnu target is meant to be self-contained for pure Rust code it bundles
// own mingw-w64 libraries. These libraries are usually not compatible with mingw-w64
// installed in the system. This breaks many cases where Rust is mixed with other languages
// (e.g. *-sys crates).
// We prefer system mingw-w64 libraries if they are available to avoid this issue.
fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> {
fn find_exe_in_path<P>(exe_name: P) -> Option<PathBuf>
where
P: AsRef<Path>,
{
for dir in env::split_paths(&env::var_os("PATH")?) {
let full_path = dir.join(&exe_name);
if full_path.is_file() {
return Some(fix_windows_verbatim_for_gcc(&full_path));
}
}
None
}
fn probe(sess: &Session) -> Option<PathBuf> {
if let (linker, LinkerFlavor::Gcc) = linker_and_flavor(&sess) {
let linker_path = if cfg!(windows) && linker.extension().is_none() {
linker.with_extension("exe")
} else {
linker
};
if let Some(linker_path) = find_exe_in_path(linker_path) {
let mingw_arch = match &sess.target.target.arch {
x if x == "x86" => "i686",
x => x,
};
let mingw_bits = &sess.target.target.target_pointer_width;
let mingw_dir = format!("{}-w64-mingw32", mingw_arch);
// Here we have path/bin/gcc but we need path/
let mut path = linker_path;
path.pop();
path.pop();
// Loosely based on Clang MinGW driver
let probe_paths = vec![
path.join(&mingw_dir).join("lib"), // Typical path
path.join(&mingw_dir).join("sys-root/mingw/lib"), // Rare path
path.join(format!(
"lib/mingw/tools/install/mingw{}/{}/lib",
&mingw_bits, &mingw_dir
)), // Chocolatey is creative
];
for probe_path in probe_paths {
if probe_path.join("crt2.o").exists() {
return Some(probe_path);
};
}
};
};
None
}
let mut system_library_path = sess.system_library_path.borrow_mut();
match &*system_library_path {
Some(Some(compiler_libs_path)) => Some(compiler_libs_path.clone()),
Some(None) => None,
None => {
let path = probe(sess);
*system_library_path = Some(path.clone());
path
}
}
}
fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
// prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
if sess.opts.cg.link_self_contained.is_none()
&& sess.target.target.llvm_target.contains("windows-gnu")
{
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
let file_path = compiler_libs_path.join(name);
if file_path.exists() {
return file_path;
}
}
}
let fs = sess.target_filesearch(PathKind::Native);
let file_path = fs.get_lib_path().join(name);
if file_path.exists() {
@ -1286,6 +1207,28 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
}
}
// Returns true if linker is located within sysroot
fn detect_self_contained_mingw(sess: &Session) -> bool {
let (linker, _) = linker_and_flavor(&sess);
// Assume `-C linker=rust-lld` as self-contained mode
if linker == Path::new("rust-lld") {
return true;
}
let linker_with_extension = if cfg!(windows) && linker.extension().is_none() {
linker.with_extension("exe")
} else {
linker
};
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
let full_path = dir.join(&linker_with_extension);
// If linker comes from sysroot assume self-contained mode
if full_path.is_file() && !full_path.starts_with(&sess.sysroot) {
return false;
}
}
true
}
/// Whether we link to our own CRT objects instead of relying on gcc to pull them.
/// We only provide such support for a very limited number of targets.
fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
@ -1298,10 +1241,10 @@ fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
// based on host and linker path, for example.
// (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237).
Some(CrtObjectsFallback::Musl) => sess.crt_static(Some(crate_type)),
// FIXME: Find some heuristic for "native mingw toolchain is available",
// likely based on `get_crt_libs_path` (https://github.com/rust-lang/rust/pull/67429).
Some(CrtObjectsFallback::Mingw) => {
sess.host == sess.target.target && sess.target.target.target_vendor != "uwp"
sess.host == sess.target.target
&& sess.target.target.target_vendor != "uwp"
&& detect_self_contained_mingw(&sess)
}
// FIXME: Figure out cases in which WASM needs to link with a native toolchain.
Some(CrtObjectsFallback::Wasm) => true,
@ -1498,16 +1441,6 @@ fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'
/// Add sysroot and other globally set directories to the directory search list.
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
// Prefer system mingw-w64 libs, see get_crt_libs_path comment for more details.
if sess.opts.cg.link_self_contained.is_none()
&& cfg!(windows)
&& sess.target.target.llvm_target.contains("windows-gnu")
{
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
cmd.include_path(&compiler_libs_path);
}
}
// The default library location, we need this to find the runtime.
// The location of crates will be determined as needed.
let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();

View file

@ -107,8 +107,14 @@ impl Inliner<'tcx> {
// Avoid a cycle here by only using `optimized_mir` only if we have
// a lower `HirId` than the callee. This ensures that the callee will
// not inline us. This trick only works without incremental compilation.
// So don't do it if that is enabled.
if !self.tcx.dep_graph.is_fully_enabled() && self_hir_id < callee_hir_id {
// So don't do it if that is enabled. Also avoid inlining into generators,
// since their `optimized_mir` is used for layout computation, which can
// create a cycle, even when no attempt is made to inline the function
// in the other direction.
if !self.tcx.dep_graph.is_fully_enabled()
&& self_hir_id < callee_hir_id
&& caller_body.generator_kind.is_none()
{
self.tcx.optimized_mir(callsite.callee)
} else {
continue;

View file

@ -685,7 +685,7 @@ impl<T> VecDeque<T> {
}
/// Tries to reserve the minimum capacity for exactly `additional` more elements to
/// be inserted in the given `VecDeque<T>`. After calling `reserve_exact`,
/// be inserted in the given `VecDeque<T>`. After calling `try_reserve_exact`,
/// capacity will be greater than or equal to `self.len() + additional`.
/// Does nothing if the capacity is already sufficient.
///
@ -727,7 +727,7 @@ impl<T> VecDeque<T> {
/// Tries to reserve capacity for at least `additional` more elements to be inserted
/// in the given `VecDeque<T>`. The collection may reserve more space to avoid
/// frequent reallocations. After calling `reserve`, capacity will be
/// frequent reallocations. After calling `try_reserve`, capacity will be
/// greater than or equal to `self.len() + additional`. Does nothing if
/// capacity is already sufficient.
///

View file

@ -523,7 +523,7 @@ impl<T> Vec<T> {
/// Tries to reserve capacity for at least `additional` more elements to be inserted
/// in the given `Vec<T>`. The collection may reserve more space to avoid
/// frequent reallocations. After calling `reserve`, capacity will be
/// frequent reallocations. After calling `try_reserve`, capacity will be
/// greater than or equal to `self.len() + additional`. Does nothing if
/// capacity is already sufficient.
///
@ -559,7 +559,7 @@ impl<T> Vec<T> {
}
/// Tries to reserves the minimum capacity for exactly `additional` more elements to
/// be inserted in the given `Vec<T>`. After calling `reserve_exact`,
/// be inserted in the given `Vec<T>`. After calling `try_reserve_exact`,
/// capacity will be greater than or equal to `self.len() + additional`.
/// Does nothing if the capacity is already sufficient.
///
@ -582,7 +582,7 @@ impl<T> Vec<T> {
/// let mut output = Vec::new();
///
/// // Pre-reserve the memory, exiting if we can't
/// output.try_reserve(data.len())?;
/// output.try_reserve_exact(data.len())?;
///
/// // Now we know this can't OOM in the middle of our complex work
/// output.extend(data.iter().map(|&val| {

View file

@ -422,4 +422,17 @@ impl<T, const N: usize> [T; N] {
// and we just need to cast it to the correct type.
unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) }
}
/// Returns a slice containing the entire array. Equivalent to `&s[..]`.
#[unstable(feature = "array_methods", issue = "76118")]
pub fn as_slice(&self) -> &[T] {
self
}
/// Returns a mutable slice containing the entire array. Equivalent to
/// `&mut s[..]`.
#[unstable(feature = "array_methods", issue = "76118")]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
}

View file

@ -1,9 +1,9 @@
use crate::cmp;
use crate::fmt;
use crate::intrinsics;
use crate::ops::{Add, AddAssign, Try};
use crate::ops::{Add, AddAssign, ControlFlow, Try};
use super::{from_fn, LoopState};
use super::from_fn;
use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen};
mod chain;
@ -1164,10 +1164,10 @@ where
#[inline]
fn find<T, B>(
f: &mut impl FnMut(T) -> Option<B>,
) -> impl FnMut((), T) -> LoopState<(), B> + '_ {
) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ {
move |(), x| match f(x) {
Some(x) => LoopState::Break(x),
None => LoopState::Continue(()),
Some(x) => ControlFlow::Break(x),
None => ControlFlow::Continue(()),
}
}
@ -1864,13 +1864,13 @@ where
flag: &'a mut bool,
p: &'a mut impl FnMut(&T) -> bool,
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
move |acc, x| {
if p(&x) {
LoopState::from_try(fold(acc, x))
ControlFlow::from_try(fold(acc, x))
} else {
*flag = true;
LoopState::Break(Try::from_ok(acc))
ControlFlow::Break(Try::from_ok(acc))
}
}
}
@ -1963,8 +1963,8 @@ where
{
let Self { iter, predicate } = self;
iter.try_fold(init, |acc, x| match predicate(x) {
Some(item) => LoopState::from_try(fold(acc, item)),
None => LoopState::Break(Try::from_ok(acc)),
Some(item) => ControlFlow::from_try(fold(acc, item)),
None => ControlFlow::Break(Try::from_ok(acc)),
})
.into_try()
}
@ -2135,11 +2135,11 @@ where
fn check<T, Acc, R: Try<Ok = Acc>>(
mut n: usize,
mut fold: impl FnMut(Acc, T) -> R,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> {
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> {
move |acc, x| {
n -= 1;
let r = fold(acc, x);
if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) }
if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
}
}
@ -2246,11 +2246,11 @@ where
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
n: &'a mut usize,
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
move |acc, x| {
*n -= 1;
let r = fold(acc, x);
if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) }
if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
}
}
@ -2414,10 +2414,10 @@ where
state: &'a mut St,
f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
mut fold: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
move |acc, x| match f(state, x) {
None => LoopState::Break(Try::from_ok(acc)),
Some(x) => LoopState::from_try(fold(acc, x)),
None => ControlFlow::Break(Try::from_ok(acc)),
Some(x) => ControlFlow::from_try(fold(acc, x)),
}
}
@ -2638,10 +2638,10 @@ where
let error = &mut *self.error;
self.iter
.try_fold(init, |acc, x| match x {
Ok(x) => LoopState::from_try(f(acc, x)),
Ok(x) => ControlFlow::from_try(f(acc, x)),
Err(e) => {
*error = Err(e);
LoopState::Break(Try::from_ok(acc))
ControlFlow::Break(Try::from_ok(acc))
}
})
.into_try()

View file

@ -308,8 +308,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::ops::Try;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::traits::Iterator;
@ -367,57 +365,3 @@ mod adapters;
mod range;
mod sources;
mod traits;
/// Used to make try_fold closures more like normal loops
#[derive(PartialEq)]
enum LoopState<C, B> {
Continue(C),
Break(B),
}
impl<C, B> Try for LoopState<C, B> {
type Ok = C;
type Error = B;
#[inline]
fn into_result(self) -> Result<Self::Ok, Self::Error> {
match self {
LoopState::Continue(y) => Ok(y),
LoopState::Break(x) => Err(x),
}
}
#[inline]
fn from_error(v: Self::Error) -> Self {
LoopState::Break(v)
}
#[inline]
fn from_ok(v: Self::Ok) -> Self {
LoopState::Continue(v)
}
}
impl<C, B> LoopState<C, B> {
#[inline]
fn break_value(self) -> Option<B> {
match self {
LoopState::Continue(..) => None,
LoopState::Break(x) => Some(x),
}
}
}
impl<R: Try> LoopState<R::Ok, R> {
#[inline]
fn from_try(r: R) -> Self {
match Try::into_result(r) {
Ok(v) => LoopState::Continue(v),
Err(v) => LoopState::Break(Try::from_error(v)),
}
}
#[inline]
fn into_try(self) -> R {
match self {
LoopState::Continue(v) => Try::from_ok(v),
LoopState::Break(v) => v,
}
}
}

View file

@ -1,5 +1,4 @@
use crate::iter::LoopState;
use crate::ops::Try;
use crate::ops::{ControlFlow, Try};
/// An iterator able to yield elements from both ends.
///
@ -309,9 +308,9 @@ pub trait DoubleEndedIterator: Iterator {
#[inline]
fn check<T>(
mut predicate: impl FnMut(&T) -> bool,
) -> impl FnMut((), T) -> LoopState<(), T> {
) -> impl FnMut((), T) -> ControlFlow<(), T> {
move |(), x| {
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}

View file

@ -3,9 +3,8 @@
// can't split that into multiple files.
use crate::cmp::{self, Ordering};
use crate::ops::{Add, Try};
use crate::ops::{Add, ControlFlow, Try};
use super::super::LoopState;
use super::super::TrustedRandomAccess;
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
use super::super::{FlatMap, Flatten};
@ -22,8 +21,8 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
/// generally, please see the [module-level documentation]. In particular, you
/// may want to know how to [implement `Iterator`][impl].
///
/// [module-level documentation]: index.html
/// [impl]: index.html#implementing-iterator
/// [module-level documentation]: crate::iter
/// [impl]: crate::iter#implementing-iterator
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(
@ -212,7 +211,7 @@ pub trait Iterator {
/// returning the number of times it saw [`Some`]. Note that [`next`] has to be
/// called at least once even if the iterator does not have any elements.
///
/// [`next`]: #tymethod.next
/// [`next`]: Iterator::next
///
/// # Overflow Behavior
///
@ -449,9 +448,7 @@ pub trait Iterator {
/// }
/// ```
///
/// [`once`]: fn.once.html
/// [`Iterator`]: trait.Iterator.html
/// [`IntoIterator`]: trait.IntoIterator.html
/// [`once`]: crate::iter::once
/// [`OsStr`]: ../../std/ffi/struct.OsStr.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -496,9 +493,6 @@ pub trait Iterator {
/// [`Iterator`] itself. For example, slices (`&[T]`) implement
/// [`IntoIterator`], and so can be passed to `zip()` directly:
///
/// [`IntoIterator`]: trait.IntoIterator.html
/// [`Iterator`]: trait.Iterator.html
///
/// ```
/// let s1 = &[1, 2, 3];
/// let s2 = &[4, 5, 6];
@ -530,8 +524,8 @@ pub trait Iterator {
/// assert_eq!((2, 'o'), zipper[2]);
/// ```
///
/// [`enumerate`]: #method.enumerate
/// [`next`]: #tymethod.next
/// [`enumerate`]: Iterator::enumerate
/// [`next`]: Iterator::next
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
@ -734,8 +728,8 @@ pub trait Iterator {
/// Why `filter_map` and not just [`filter`] and [`map`]? The key is in this
/// part:
///
/// [`filter`]: #method.filter
/// [`map`]: #method.map
/// [`filter`]: Iterator::filter
/// [`map`]: Iterator::map
///
/// > If the closure returns [`Some(element)`][`Some`], then that element is returned.
///
@ -802,7 +796,7 @@ pub trait Iterator {
///
/// [`usize`]: type@usize
/// [`usize::MAX`]: crate::usize::MAX
/// [`zip`]: #method.zip
/// [`zip`]: Iterator::zip
///
/// # Examples
///
@ -837,8 +831,8 @@ pub trait Iterator {
/// anything other than fetching the next value) of the [`next`] method
/// will occur.
///
/// [`peek`]: crate::iter::Peekable::peek
/// [`next`]: #tymethod.next
/// [`peek`]: Peekable::peek
/// [`next`]: Iterator::next
///
/// # Examples
///
@ -876,7 +870,7 @@ pub trait Iterator {
/// Creates an iterator that [`skip`]s elements based on a predicate.
///
/// [`skip`]: #method.skip
/// [`skip`]: Iterator::skip
///
/// `skip_while()` takes a closure as an argument. It will call this
/// closure on each element of the iterator, and ignore elements
@ -1043,8 +1037,8 @@ pub trait Iterator {
///
/// Here's the same example, but with [`take_while`] and [`map`]:
///
/// [`take_while`]: #method.take_while
/// [`map`]: #method.map
/// [`take_while`]: Iterator::take_while
/// [`map`]: Iterator::map
///
/// ```
/// let a = [-1i32, 4, 0, 1];
@ -1104,7 +1098,7 @@ pub trait Iterator {
/// It is also not specified what this iterator returns after the first` None` is returned.
/// If you need fused iterator, use [`fuse`].
///
/// [`fuse`]: #method.fuse
/// [`fuse`]: Iterator::fuse
#[inline]
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
@ -1190,7 +1184,7 @@ pub trait Iterator {
/// An iterator adaptor similar to [`fold`] that holds internal state and
/// produces a new iterator.
///
/// [`fold`]: #method.fold
/// [`fold`]: Iterator::fold
///
/// `scan()` takes two arguments: an initial value which seeds the internal
/// state, and a closure with two arguments, the first being a mutable
@ -1246,8 +1240,8 @@ pub trait Iterator {
/// one item for each element, and `flat_map()`'s closure returns an
/// iterator for each element.
///
/// [`map`]: #method.map
/// [`flatten`]: #method.flatten
/// [`map`]: Iterator::map
/// [`flatten`]: Iterator::flatten
///
/// # Examples
///
@ -1333,7 +1327,7 @@ pub trait Iterator {
/// two-dimensional and not one-dimensional. To get a one-dimensional
/// structure, you have to `flatten()` again.
///
/// [`flat_map()`]: #method.flat_map
/// [`flat_map()`]: Iterator::flat_map
#[inline]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
fn flatten(self) -> Flatten<Self>
@ -1640,7 +1634,7 @@ pub trait Iterator {
/// assert_eq!(Ok(vec![1, 3]), result);
/// ```
///
/// [`iter`]: #tymethod.next
/// [`iter`]: Iterator::next
/// [`String`]: ../../std/string/struct.String.html
/// [`char`]: type@char
#[inline]
@ -1661,8 +1655,8 @@ pub trait Iterator {
///
/// See also [`is_partitioned()`] and [`partition_in_place()`].
///
/// [`is_partitioned()`]: #method.is_partitioned
/// [`partition_in_place()`]: #method.partition_in_place
/// [`is_partitioned()`]: Iterator::is_partitioned
/// [`partition_in_place()`]: Iterator::partition_in_place
///
/// # Examples
///
@ -1716,8 +1710,8 @@ pub trait Iterator {
///
/// See also [`is_partitioned()`] and [`partition()`].
///
/// [`is_partitioned()`]: #method.is_partitioned
/// [`partition()`]: #method.partition
/// [`is_partitioned()`]: Iterator::is_partitioned
/// [`partition()`]: Iterator::partition
///
/// # Examples
///
@ -1779,8 +1773,8 @@ pub trait Iterator {
///
/// See also [`partition()`] and [`partition_in_place()`].
///
/// [`partition()`]: #method.partition
/// [`partition_in_place()`]: #method.partition_in_place
/// [`partition()`]: Iterator::partition
/// [`partition_in_place()`]: Iterator::partition_in_place
///
/// # Examples
///
@ -1879,8 +1873,8 @@ pub trait Iterator {
/// This can also be thought of as the fallible form of [`for_each()`]
/// or as the stateless version of [`try_fold()`].
///
/// [`for_each()`]: #method.for_each
/// [`try_fold()`]: #method.try_fold
/// [`for_each()`]: Iterator::for_each
/// [`try_fold()`]: Iterator::try_fold
///
/// # Examples
///
@ -2006,11 +2000,13 @@ pub trait Iterator {
accum
}
/// The same as [`fold()`](#method.fold), but uses the first element in the
/// The same as [`fold()`], but uses the first element in the
/// iterator as the initial value, folding every subsequent element into it.
/// If the iterator is empty, return `None`; otherwise, return the result
/// of the fold.
///
/// [`fold()`]: Iterator::fold
///
/// # Example
///
/// Find the maximum value:
@ -2088,12 +2084,12 @@ pub trait Iterator {
F: FnMut(Self::Item) -> bool,
{
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> {
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
move |(), x| {
if f(x) { LoopState::Continue(()) } else { LoopState::Break(()) }
if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
}
}
self.try_fold((), check(f)) == LoopState::Continue(())
self.try_fold((), check(f)) == ControlFlow::Continue(())
}
/// Tests if any element of the iterator matches a predicate.
@ -2141,13 +2137,13 @@ pub trait Iterator {
F: FnMut(Self::Item) -> bool,
{
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> {
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
move |(), x| {
if f(x) { LoopState::Break(()) } else { LoopState::Continue(()) }
if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
}
}
self.try_fold((), check(f)) == LoopState::Break(())
self.try_fold((), check(f)) == ControlFlow::Break(())
}
/// Searches for an element of an iterator that satisfies a predicate.
@ -2203,9 +2199,9 @@ pub trait Iterator {
#[inline]
fn check<T>(
mut predicate: impl FnMut(&T) -> bool,
) -> impl FnMut((), T) -> LoopState<(), T> {
) -> impl FnMut((), T) -> ControlFlow<(), T> {
move |(), x| {
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
@ -2235,10 +2231,12 @@ pub trait Iterator {
F: FnMut(Self::Item) -> Option<B>,
{
#[inline]
fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> LoopState<(), B> {
fn check<T, B>(
mut f: impl FnMut(T) -> Option<B>,
) -> impl FnMut((), T) -> ControlFlow<(), B> {
move |(), x| match f(x) {
Some(x) => LoopState::Break(x),
None => LoopState::Continue(()),
Some(x) => ControlFlow::Break(x),
None => ControlFlow::Continue(()),
}
}
@ -2274,15 +2272,15 @@ pub trait Iterator {
R: Try<Ok = bool>,
{
#[inline]
fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result<T, R::Error>>
fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<(), Result<T, R::Error>>
where
F: FnMut(&T) -> R,
R: Try<Ok = bool>,
{
move |(), x| match f(&x).into_result() {
Ok(false) => LoopState::Continue(()),
Ok(true) => LoopState::Break(Ok(x)),
Err(x) => LoopState::Break(Err(x)),
Ok(false) => ControlFlow::Continue(()),
Ok(true) => ControlFlow::Break(Ok(x)),
Err(x) => ControlFlow::Break(Err(x)),
}
}
@ -2352,10 +2350,14 @@ pub trait Iterator {
#[inline]
fn check<T>(
mut predicate: impl FnMut(T) -> bool,
) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
// The addition might panic on overflow
move |i, x| {
if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(Add::add(i, 1)) }
if predicate(x) {
ControlFlow::Break(i)
} else {
ControlFlow::Continue(Add::add(i, 1))
}
}
}
@ -2411,10 +2413,10 @@ pub trait Iterator {
#[inline]
fn check<T>(
mut predicate: impl FnMut(T) -> bool,
) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
move |i, x| {
let i = i - 1;
if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(i) }
if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) }
}
}
@ -2602,8 +2604,6 @@ pub trait Iterator {
/// This is only possible if the iterator has an end, so `rev()` only
/// works on [`DoubleEndedIterator`]s.
///
/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
///
/// # Examples
///
/// ```
@ -2634,7 +2634,7 @@ pub trait Iterator {
///
/// This function is, in some sense, the opposite of [`zip`].
///
/// [`zip`]: #method.zip
/// [`zip`]: Iterator::zip
///
/// # Examples
///
@ -2713,7 +2713,7 @@ pub trait Iterator {
/// This is useful when you have an iterator over `&T`, but you need an
/// iterator over `T`.
///
/// [`clone`]: crate::clone::Clone::clone
/// [`clone`]: Clone::clone
///
/// # Examples
///
@ -3201,7 +3201,7 @@ pub trait Iterator {
/// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// ```
///
/// [`is_sorted`]: #method.is_sorted
/// [`is_sorted`]: Iterator::is_sorted
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
fn is_sorted_by<F>(mut self, mut compare: F) -> bool
where
@ -3230,7 +3230,7 @@ pub trait Iterator {
/// the elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see
/// its documentation for more information.
///
/// [`is_sorted`]: #method.is_sorted
/// [`is_sorted`]: Iterator::is_sorted
///
/// # Examples
///

View file

@ -111,13 +111,13 @@ pub trait Sized {
/// - `T` is not part of the type of any other fields
/// - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
///
/// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow
/// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized
/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
/// "user-defined" containers such as [`Rc`] to contain dynamically-sized
/// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce]
/// for more details.
///
/// [coerceunsized]: ../ops/trait.CoerceUnsized.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [`ops::CoerceUnsized`]: crate::ops::CoerceUnsized
/// [`Rc`]: ../../std/rc/struct.Rc.html
/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
/// [nomicon-coerce]: ../../nomicon/coercions.html
#[unstable(feature = "unsize", issue = "27732")]
@ -368,11 +368,7 @@ pub trait StructuralEq {
///
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
/// [`String`]: ../../std/string/struct.String.html
/// [`Drop`]: ../../std/ops/trait.Drop.html
/// [`size_of::<T>`]: ../../std/mem/fn.size_of.html
/// [`Clone`]: ../clone/trait.Clone.html
/// [`String`]: ../../std/string/struct.String.html
/// [`i32`]: ../../std/primitive.i32.html
/// [`size_of::<T>`]: crate::mem::size_of
/// [impls]: #implementors
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "copy"]
@ -400,18 +396,18 @@ pub macro Copy($item:item) {
/// This trait is automatically implemented when the compiler determines
/// it's appropriate.
///
/// The precise definition is: a type `T` is `Sync` if and only if `&T` is
/// [`Send`][send]. In other words, if there is no possibility of
/// The precise definition is: a type `T` is [`Sync`] if and only if `&T` is
/// [`Send`]. In other words, if there is no possibility of
/// [undefined behavior][ub] (including data races) when passing
/// `&T` references between threads.
///
/// As one would expect, primitive types like [`u8`][u8] and [`f64`][f64]
/// are all `Sync`, and so are simple aggregate types containing them,
/// like tuples, structs and enums. More examples of basic `Sync`
/// As one would expect, primitive types like [`u8`] and [`f64`]
/// are all [`Sync`], and so are simple aggregate types containing them,
/// like tuples, structs and enums. More examples of basic [`Sync`]
/// types include "immutable" types like `&T`, and those with simple
/// inherited mutability, such as [`Box<T>`][box], [`Vec<T>`][vec] and
/// most other collection types. (Generic parameters need to be `Sync`
/// for their container to be `Sync`.)
/// most other collection types. (Generic parameters need to be [`Sync`]
/// for their container to be [`Sync`].)
///
/// A somewhat surprising consequence of the definition is that `&mut T`
/// is `Sync` (if `T` is `Sync`) even though it seems like that might
@ -421,15 +417,15 @@ pub macro Copy($item:item) {
/// of a data race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe form, such as [`cell::Cell`][cell]
/// and [`cell::RefCell`][refcell]. These types allow for mutation of
/// mutability" in a non-thread-safe form, such as [`Cell`][cell]
/// and [`RefCell`][refcell]. These types allow for mutation of
/// their contents even through an immutable, shared reference. For
/// example the `set` method on [`Cell<T>`][cell] takes `&self`, so it requires
/// only a shared reference [`&Cell<T>`][cell]. The method performs no
/// synchronization, thus [`Cell`][cell] cannot be `Sync`.
///
/// Another example of a non-`Sync` type is the reference-counting
/// pointer [`rc::Rc`][rc]. Given any reference [`&Rc<T>`][rc], you can clone
/// pointer [`Rc`][rc]. Given any reference [`&Rc<T>`][rc], you can clone
/// a new [`Rc<T>`][rc], modifying the reference counts in a non-atomic way.
///
/// For cases when one does need thread-safe interior mutability,
@ -445,24 +441,21 @@ pub macro Copy($item:item) {
/// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing
/// from `&T` to `&mut T` is invalid.
///
/// See [the Nomicon](../../nomicon/send-and-sync.html) for more
/// details about `Sync`.
/// See [the Nomicon][nomicon-send-and-sync] for more details about `Sync`.
///
/// [send]: trait.Send.html
/// [u8]: ../../std/primitive.u8.html
/// [f64]: ../../std/primitive.f64.html
/// [box]: ../../std/boxed/struct.Box.html
/// [vec]: ../../std/vec/struct.Vec.html
/// [cell]: ../cell/struct.Cell.html
/// [refcell]: ../cell/struct.RefCell.html
/// [cell]: crate::cell::Cell
/// [refcell]: crate::cell::RefCell
/// [rc]: ../../std/rc/struct.Rc.html
/// [arc]: ../../std/sync/struct.Arc.html
/// [atomic data types]: ../sync/atomic/index.html
/// [atomic data types]: crate::sync::atomic
/// [mutex]: ../../std/sync/struct.Mutex.html
/// [rwlock]: ../../std/sync/struct.RwLock.html
/// [unsafecell]: ../cell/struct.UnsafeCell.html
/// [unsafecell]: crate::cell::UnsafeCell
/// [ub]: ../../reference/behavior-considered-undefined.html
/// [transmute]: ../../std/mem/fn.transmute.html
/// [transmute]: crate::mem::transmute
/// [nomicon-send-and-sync]: ../../nomicon/send-and-sync.html
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")]
#[lang = "sync"]
@ -698,7 +691,7 @@ mod impls {
/// guarantees to [`mem::Discriminant`]. It is **undefined behavior** to transmute
/// between `DiscriminantKind::Discriminant` and `mem::Discriminant`.
///
/// [`mem::Discriminant`]: https://doc.rust-lang.org/stable/core/mem/struct.Discriminant.html
/// [`mem::Discriminant`]: crate::mem::Discriminant
#[unstable(
feature = "discriminant_kind",
issue = "none",
@ -733,7 +726,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
///
/// The [`Pin`][Pin] type is used instead to prevent moves through the type
/// system. Pointers `P<T>` wrapped in the [`Pin<P<T>>`][Pin] wrapper can't be
/// moved out of. See the [`pin module`] documentation for more information on
/// moved out of. See the [`pin` module] documentation for more information on
/// pinning.
///
/// Implementing the `Unpin` trait for `T` lifts the restrictions of pinning off
@ -764,9 +757,9 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
///
/// This trait is automatically implemented for almost every type.
///
/// [`mem::replace`]: ../../std/mem/fn.replace.html
/// [`mem::replace`]: crate::mem::replace
/// [Pin]: crate::pin::Pin
/// [`pin module`]: crate::pin
/// [`pin` module]: crate::pin
#[stable(feature = "pin", since = "1.33.0")]
#[rustc_on_unimplemented(
on(_Self = "std::future::Future", note = "consider using `Box::pin`",),

View file

@ -0,0 +1,67 @@
use crate::ops::Try;
/// Used to make try_fold closures more like normal loops
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ControlFlow<C, B> {
/// Continue in the loop, using the given value for the next iteration
Continue(C),
/// Exit the loop, yielding the given value
Break(B),
}
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
impl<C, B> Try for ControlFlow<C, B> {
type Ok = C;
type Error = B;
#[inline]
fn into_result(self) -> Result<Self::Ok, Self::Error> {
match self {
ControlFlow::Continue(y) => Ok(y),
ControlFlow::Break(x) => Err(x),
}
}
#[inline]
fn from_error(v: Self::Error) -> Self {
ControlFlow::Break(v)
}
#[inline]
fn from_ok(v: Self::Ok) -> Self {
ControlFlow::Continue(v)
}
}
impl<C, B> ControlFlow<C, B> {
/// Converts the `ControlFlow` into an `Option` which is `Some` if the
/// `ControlFlow` was `Break` and `None` otherwise.
#[inline]
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
pub fn break_value(self) -> Option<B> {
match self {
ControlFlow::Continue(..) => None,
ControlFlow::Break(x) => Some(x),
}
}
}
impl<R: Try> ControlFlow<R::Ok, R> {
/// Create a `ControlFlow` from any type implementing `Try`.
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
#[inline]
pub fn from_try(r: R) -> Self {
match Try::into_result(r) {
Ok(v) => ControlFlow::Continue(v),
Err(v) => ControlFlow::Break(Try::from_error(v)),
}
}
/// Convert a `ControlFlow` into any type implementing `Try`;
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
#[inline]
pub fn into_try(self) -> R {
match self {
ControlFlow::Continue(v) => Try::from_ok(v),
ControlFlow::Break(v) => v,
}
}
}

View file

@ -140,6 +140,7 @@
mod arith;
mod bit;
mod control_flow;
mod deref;
mod drop;
mod function;
@ -191,3 +192,6 @@ pub use self::unsize::CoerceUnsized;
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
pub use self::unsize::DispatchFromDyn;
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
pub use self::control_flow::ControlFlow;

View file

@ -1,5 +1,6 @@
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_map)]
#![feature(bool_to_option)]
#![feature(bound_cloned)]

View file

@ -1,4 +1,3 @@
use core::array::FixedSizeArray;
use core::clone::Clone;
use core::mem;
use core::ops::DerefMut;

View file

@ -1,4 +1,3 @@
use core::array::FixedSizeArray;
use core::ops::DerefMut;
use core::option::*;

View file

@ -52,11 +52,14 @@ where
W: Write,
{
let mut buf = MaybeUninit::<[u8; super::DEFAULT_BUF_SIZE]>::uninit();
// FIXME(#76092): This is calling `get_mut` and `get_ref` on an uninitialized
// `MaybeUninit`. Revisit this once we decided whether that is valid or not.
// This is still technically undefined behavior due to creating a reference
// to uninitialized data, but within libstd we can rely on more guarantees
// than if this code were in an external lib.
// FIXME: #42788
//
// - This creates a (mut) reference to a slice of
// _uninitialized_ integers, which is **undefined behavior**
//
// - Only the standard library gets to soundly "ignore" this,
// based on its privileged knowledge of unstable rustc
// internals;
unsafe {
reader.initializer().initialize(buf.assume_init_mut());
}

View file

@ -240,6 +240,7 @@
#![feature(const_fn_transmute)]
#![feature(const_ipv6)]
#![feature(const_raw_ptr_deref)]
#![feature(const_ipv4)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
#![feature(custom_test_frameworks)]

View file

@ -365,8 +365,9 @@ impl Ipv4Addr {
/// let addr = Ipv4Addr::new(127, 0, 0, 1);
/// assert_eq!(addr.octets(), [127, 0, 0, 1]);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn octets(&self) -> [u8; 4] {
pub const fn octets(&self) -> [u8; 4] {
// This returns the order we want because s_addr is stored in big-endian.
self.inner.s_addr.to_ne_bytes()
}
@ -408,8 +409,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
/// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_loopback(&self) -> bool {
pub const fn is_loopback(&self) -> bool {
self.octets()[0] == 127
}
@ -437,8 +439,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
/// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_private(&self) -> bool {
pub const fn is_private(&self) -> bool {
match self.octets() {
[10, ..] => true,
[172, b, ..] if b >= 16 && b <= 31 => true,
@ -463,8 +466,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
/// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_link_local(&self) -> bool {
pub const fn is_link_local(&self) -> bool {
match self.octets() {
[169, 254, ..] => true,
_ => false,
@ -542,10 +546,13 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
/// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
/// ```
pub fn is_global(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_global(&self) -> bool {
// check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
// globally routable addresses in the 192.0.0.0/24 range.
if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
if u32::from_be_bytes(self.octets()) == 0xc0000009
|| u32::from_be_bytes(self.octets()) == 0xc000000a
{
return true;
}
!self.is_private()
@ -577,7 +584,8 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
/// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
/// ```
pub fn is_shared(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_shared(&self) -> bool {
self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
}
@ -609,7 +617,8 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
/// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
/// ```
pub fn is_ietf_protocol_assignment(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_ietf_protocol_assignment(&self) -> bool {
self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
}
@ -632,7 +641,8 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
/// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
/// ```
pub fn is_benchmarking(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_benchmarking(&self) -> bool {
self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
}
@ -664,7 +674,8 @@ impl Ipv4Addr {
/// // The broadcast address is not considered as reserved for future use by this implementation
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
/// ```
pub fn is_reserved(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_reserved(&self) -> bool {
self.octets()[0] & 240 == 240 && !self.is_broadcast()
}
@ -685,8 +696,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
/// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_multicast(&self) -> bool {
pub const fn is_multicast(&self) -> bool {
self.octets()[0] >= 224 && self.octets()[0] <= 239
}
@ -705,9 +717,10 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
/// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_broadcast(&self) -> bool {
self == &Self::BROADCAST
pub const fn is_broadcast(&self) -> bool {
u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
}
/// Returns [`true`] if this address is in a range designated for documentation.
@ -731,8 +744,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
/// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_documentation(&self) -> bool {
pub const fn is_documentation(&self) -> bool {
match self.octets() {
[192, 0, 2, _] => true,
[198, 51, 100, _] => true,
@ -745,6 +759,9 @@ impl Ipv4Addr {
///
/// a.b.c.d becomes ::a.b.c.d
///
/// This isn't typically the method you want; these addresses don't typically
/// function on modern systems. Use `to_ipv6_mapped` instead.
///
/// [`IPv6` address]: Ipv6Addr
///
/// # Examples
@ -757,10 +774,13 @@ impl Ipv4Addr {
/// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
/// );
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
let [a, b, c, d] = self.octets();
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
Ipv6Addr {
inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] },
}
}
/// Converts this address to an IPv4-mapped [`IPv6` address].
@ -777,10 +797,13 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
/// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
let [a, b, c, d] = self.octets();
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d])
Ipv6Addr {
inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] },
}
}
}

View file

@ -510,7 +510,7 @@ mod prim_pointer {}
/// an array. Indeed, this provides most of the API for working with arrays.
/// Slices have a dynamic size and do not coerce to arrays.
///
/// You can move elements out of an array with a slice pattern. If you want
/// You can move elements out of an array with a [slice pattern]. If you want
/// one element, see [`mem::replace`].
///
/// # Examples
@ -552,7 +552,7 @@ mod prim_pointer {}
/// for x in &array { }
/// ```
///
/// You can use a slice pattern to move elements out of an array:
/// You can use a [slice pattern] to move elements out of an array:
///
/// ```
/// fn move_away(_: String) { /* Do interesting things. */ }
@ -567,7 +567,7 @@ mod prim_pointer {}
/// [`Hash`]: hash::Hash
/// [`Borrow`]: borrow::Borrow
/// [`BorrowMut`]: borrow::BorrowMut
///
/// [slice pattern]: ../reference/patterns.html#slice-patterns
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_array {}

@ -1 +1 @@
Subproject commit c0a6a61b8205da14ac955425f74258ffd8ee065d
Subproject commit e5ed97128302d5fa45dbac0e64426bc7649a558c

@ -1 +1 @@
Subproject commit bd6e4a9f59c5c1545f572266af77f5c7a5bad6d1
Subproject commit 81f16863014de60b53de401d71ff904d163ee030

@ -1 +1 @@
Subproject commit 1b6c4b0afab97c0230433466c97167bbbe8445f6
Subproject commit 25391dba46262f882fa846beefaff54a966a8fa5

@ -1 +1 @@
Subproject commit 80a10e22140e28392b99d24ed02f4c6d8cb770a0
Subproject commit 19f0a0372af497b34369cf182d9d16156cab2969

View file

@ -0,0 +1,18 @@
// Checks that inliner doesn't introduce cycles when optimizing generators.
// The outcome of optimization is not verfied, just the absence of the cycle.
// Regression test for #76181.
//
// edition:2018
#![crate_type = "lib"]
pub struct S;
impl S {
pub async fn g(&mut self) {
self.h();
}
pub fn h(&mut self) {
let _ = self.g();
}
}

View file

@ -0,0 +1,58 @@
// run-pass
#![feature(ip)]
#![feature(const_ipv4)]
use std::net::{Ipv4Addr, Ipv6Addr};
fn main() {
const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
const OCTETS: [u8; 4] = IP_ADDRESS.octets();
assert_eq!(OCTETS, [127, 0, 0, 1]);
const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
assert!(!IS_UNSPECIFIED);
const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
assert!(IS_LOOPBACK);
const IS_PRIVATE : bool = IP_ADDRESS.is_private();
assert!(!IS_PRIVATE);
const IS_LINK_LOCAL : bool = IP_ADDRESS.is_link_local();
assert!(!IS_LINK_LOCAL);
const IS_GLOBAL : bool = IP_ADDRESS.is_global();
assert!(!IS_GLOBAL);
const IS_SHARED : bool = IP_ADDRESS.is_shared();
assert!(!IS_SHARED);
const IS_IETF_PROTOCOL_ASSIGNMENT : bool = IP_ADDRESS.is_ietf_protocol_assignment();
assert!(!IS_IETF_PROTOCOL_ASSIGNMENT);
const IS_BENCHMARKING : bool = IP_ADDRESS.is_benchmarking();
assert!(!IS_BENCHMARKING);
const IS_RESERVED : bool = IP_ADDRESS.is_reserved();
assert!(!IS_RESERVED);
const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
assert!(!IS_MULTICAST);
const IS_BROADCAST : bool = IP_ADDRESS.is_broadcast();
assert!(!IS_BROADCAST);
const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
assert!(!IS_DOCUMENTATION);
const IP_V6_COMPATIBLE : Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
assert_eq!(IP_V6_COMPATIBLE,
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1]));
const IP_V6_MAPPED : Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
assert_eq!(IP_V6_MAPPED,
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1]));
}