Auto merge of #131672 - matthiaskrgr:rollup-gyzysj4, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #128967 (std::fs::get_path freebsd update.) - #130629 (core/net: add Ipv[46]Addr::from_octets, Ipv6Addr::from_segments.) - #131274 (library: Const-stabilize `MaybeUninit::assume_init_mut`) - #131473 (compiler: `{TyAnd,}Layout` comes home) - #131533 (emscripten: Use the latest emsdk 3.1.68) - #131593 (miri: avoid cloning AllocExtra) - #131616 (merge const_ipv4 / const_ipv6 feature gate into 'ip' feature gate) - #131660 (Also use outermost const-anon for impl items in `non_local_defs` lint) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
17a19e684c
49 changed files with 469 additions and 338 deletions
254
compiler/rustc_abi/src/callconv.rs
Normal file
254
compiler/rustc_abi/src/callconv.rs
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
mod abi {
|
||||||
|
pub(crate) use crate::Primitive::*;
|
||||||
|
pub(crate) use crate::Variants;
|
||||||
|
}
|
||||||
|
|
||||||
|
use rustc_macros::HashStable_Generic;
|
||||||
|
|
||||||
|
use crate::{Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
|
pub enum RegKind {
|
||||||
|
Integer,
|
||||||
|
Float,
|
||||||
|
Vector,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
|
pub struct Reg {
|
||||||
|
pub kind: RegKind,
|
||||||
|
pub size: Size,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! reg_ctor {
|
||||||
|
($name:ident, $kind:ident, $bits:expr) => {
|
||||||
|
pub fn $name() -> Reg {
|
||||||
|
Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reg {
|
||||||
|
reg_ctor!(i8, Integer, 8);
|
||||||
|
reg_ctor!(i16, Integer, 16);
|
||||||
|
reg_ctor!(i32, Integer, 32);
|
||||||
|
reg_ctor!(i64, Integer, 64);
|
||||||
|
reg_ctor!(i128, Integer, 128);
|
||||||
|
|
||||||
|
reg_ctor!(f32, Float, 32);
|
||||||
|
reg_ctor!(f64, Float, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reg {
|
||||||
|
pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
match self.kind {
|
||||||
|
RegKind::Integer => match self.size.bits() {
|
||||||
|
1 => dl.i1_align.abi,
|
||||||
|
2..=8 => dl.i8_align.abi,
|
||||||
|
9..=16 => dl.i16_align.abi,
|
||||||
|
17..=32 => dl.i32_align.abi,
|
||||||
|
33..=64 => dl.i64_align.abi,
|
||||||
|
65..=128 => dl.i128_align.abi,
|
||||||
|
_ => panic!("unsupported integer: {self:?}"),
|
||||||
|
},
|
||||||
|
RegKind::Float => match self.size.bits() {
|
||||||
|
16 => dl.f16_align.abi,
|
||||||
|
32 => dl.f32_align.abi,
|
||||||
|
64 => dl.f64_align.abi,
|
||||||
|
128 => dl.f128_align.abi,
|
||||||
|
_ => panic!("unsupported float: {self:?}"),
|
||||||
|
},
|
||||||
|
RegKind::Vector => dl.vector_align(self.size).abi,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return value from the `homogeneous_aggregate` test function.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum HomogeneousAggregate {
|
||||||
|
/// Yes, all the "leaf fields" of this struct are passed in the
|
||||||
|
/// same way (specified in the `Reg` value).
|
||||||
|
Homogeneous(Reg),
|
||||||
|
|
||||||
|
/// There are no leaf fields at all.
|
||||||
|
NoData,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error from the `homogeneous_aggregate` test function, indicating
|
||||||
|
/// there are distinct leaf fields passed in different ways,
|
||||||
|
/// or this is uninhabited.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct Heterogeneous;
|
||||||
|
|
||||||
|
impl HomogeneousAggregate {
|
||||||
|
/// If this is a homogeneous aggregate, returns the homogeneous
|
||||||
|
/// unit, else `None`.
|
||||||
|
pub fn unit(self) -> Option<Reg> {
|
||||||
|
match self {
|
||||||
|
HomogeneousAggregate::Homogeneous(reg) => Some(reg),
|
||||||
|
HomogeneousAggregate::NoData => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
|
||||||
|
/// the same `struct`. Only succeeds if only one of them has any data,
|
||||||
|
/// or both units are identical.
|
||||||
|
fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
|
||||||
|
match (self, other) {
|
||||||
|
(x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
|
||||||
|
|
||||||
|
(HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
|
||||||
|
if a != b {
|
||||||
|
return Err(Heterogeneous);
|
||||||
|
}
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
|
/// Returns `true` if this is an aggregate type (including a ScalarPair!)
|
||||||
|
pub fn is_aggregate(&self) -> bool {
|
||||||
|
match self.abi {
|
||||||
|
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
|
||||||
|
Abi::ScalarPair(..) | Abi::Aggregate { .. } => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Homogeneous` if this layout is an aggregate containing fields of
|
||||||
|
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
|
||||||
|
/// special-cased in ABIs.
|
||||||
|
///
|
||||||
|
/// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
|
||||||
|
///
|
||||||
|
/// This is public so that it can be used in unit tests, but
|
||||||
|
/// should generally only be relevant to the ABI details of
|
||||||
|
/// specific targets.
|
||||||
|
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
|
{
|
||||||
|
match self.abi {
|
||||||
|
Abi::Uninhabited => Err(Heterogeneous),
|
||||||
|
|
||||||
|
// The primitive for this algorithm.
|
||||||
|
Abi::Scalar(scalar) => {
|
||||||
|
let kind = match scalar.primitive() {
|
||||||
|
abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
|
||||||
|
abi::Float(_) => RegKind::Float,
|
||||||
|
};
|
||||||
|
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
|
||||||
|
}
|
||||||
|
|
||||||
|
Abi::Vector { .. } => {
|
||||||
|
assert!(!self.is_zst());
|
||||||
|
Ok(HomogeneousAggregate::Homogeneous(Reg {
|
||||||
|
kind: RegKind::Vector,
|
||||||
|
size: self.size,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
|
||||||
|
// Helper for computing `homogeneous_aggregate`, allowing a custom
|
||||||
|
// starting offset (used below for handling variants).
|
||||||
|
let from_fields_at =
|
||||||
|
|layout: Self,
|
||||||
|
start: Size|
|
||||||
|
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
|
||||||
|
let is_union = match layout.fields {
|
||||||
|
FieldsShape::Primitive => {
|
||||||
|
unreachable!("aggregates can't have `FieldsShape::Primitive`")
|
||||||
|
}
|
||||||
|
FieldsShape::Array { count, .. } => {
|
||||||
|
assert_eq!(start, Size::ZERO);
|
||||||
|
|
||||||
|
let result = if count > 0 {
|
||||||
|
layout.field(cx, 0).homogeneous_aggregate(cx)?
|
||||||
|
} else {
|
||||||
|
HomogeneousAggregate::NoData
|
||||||
|
};
|
||||||
|
return Ok((result, layout.size));
|
||||||
|
}
|
||||||
|
FieldsShape::Union(_) => true,
|
||||||
|
FieldsShape::Arbitrary { .. } => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = HomogeneousAggregate::NoData;
|
||||||
|
let mut total = start;
|
||||||
|
|
||||||
|
for i in 0..layout.fields.count() {
|
||||||
|
let field = layout.field(cx, i);
|
||||||
|
if field.is_1zst() {
|
||||||
|
// No data here and no impact on layout, can be ignored.
|
||||||
|
// (We might be able to also ignore all aligned ZST but that's less clear.)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !is_union && total != layout.fields.offset(i) {
|
||||||
|
// This field isn't just after the previous one we considered, abort.
|
||||||
|
return Err(Heterogeneous);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result.merge(field.homogeneous_aggregate(cx)?)?;
|
||||||
|
|
||||||
|
// Keep track of the offset (without padding).
|
||||||
|
let size = field.size;
|
||||||
|
if is_union {
|
||||||
|
total = total.max(size);
|
||||||
|
} else {
|
||||||
|
total += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((result, total))
|
||||||
|
};
|
||||||
|
|
||||||
|
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
|
||||||
|
|
||||||
|
match &self.variants {
|
||||||
|
abi::Variants::Single { .. } => {}
|
||||||
|
abi::Variants::Multiple { variants, .. } => {
|
||||||
|
// Treat enum variants like union members.
|
||||||
|
// HACK(eddyb) pretend the `enum` field (discriminant)
|
||||||
|
// is at the start of every variant (otherwise the gap
|
||||||
|
// at the start of all variants would disqualify them).
|
||||||
|
//
|
||||||
|
// NB: for all tagged `enum`s (which include all non-C-like
|
||||||
|
// `enum`s with defined FFI representation), this will
|
||||||
|
// match the homogeneous computation on the equivalent
|
||||||
|
// `struct { tag; union { variant1; ... } }` and/or
|
||||||
|
// `union { struct { tag; variant1; } ... }`
|
||||||
|
// (the offsets of variant fields should be identical
|
||||||
|
// between the two for either to be a homogeneous aggregate).
|
||||||
|
let variant_start = total;
|
||||||
|
for variant_idx in variants.indices() {
|
||||||
|
let (variant_result, variant_total) =
|
||||||
|
from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;
|
||||||
|
|
||||||
|
result = result.merge(variant_result)?;
|
||||||
|
total = total.max(variant_total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// There needs to be no padding.
|
||||||
|
if total != self.size {
|
||||||
|
Err(Heterogeneous)
|
||||||
|
} else {
|
||||||
|
match result {
|
||||||
|
HomogeneousAggregate::Homogeneous(_) => {
|
||||||
|
assert_ne!(total, Size::ZERO);
|
||||||
|
}
|
||||||
|
HomogeneousAggregate::NoData => {
|
||||||
|
assert_eq!(total, Size::ZERO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Abi::Aggregate { sized: false } => Err(Heterogeneous),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,10 @@ use crate::{
|
||||||
Variants, WrappingRange,
|
Variants, WrappingRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod ty;
|
||||||
|
|
||||||
|
pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
|
||||||
|
|
||||||
// A variant is absent if it's uninhabited and only has ZST fields.
|
// A variant is absent if it's uninhabited and only has ZST fields.
|
||||||
// Present uninhabited variants only require space for their fields,
|
// Present uninhabited variants only require space for their fields,
|
||||||
// but *not* an encoding of the discriminant (e.g., a tag value).
|
// but *not* an encoding of the discriminant (e.g., a tag value).
|
||||||
|
|
|
@ -6,18 +6,8 @@ use Primitive::*;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
|
|
||||||
use crate::json::{Json, ToJson};
|
|
||||||
|
|
||||||
pub mod call;
|
|
||||||
|
|
||||||
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||||
pub use rustc_abi::{Float, *};
|
use crate::{Float, *};
|
||||||
|
|
||||||
impl ToJson for Endian {
|
|
||||||
fn to_json(&self) -> Json {
|
|
||||||
self.as_str().to_json()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
rustc_index::newtype_index! {
|
||||||
/// The *source-order* index of a field in a variant.
|
/// The *source-order* index of a field in a variant.
|
|
@ -1,6 +1,7 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||||
#![cfg_attr(feature = "nightly", doc(rust_logo))]
|
#![cfg_attr(feature = "nightly", doc(rust_logo))]
|
||||||
|
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
||||||
#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
|
#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
|
||||||
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
||||||
#![warn(unreachable_pub)]
|
#![warn(unreachable_pub)]
|
||||||
|
@ -22,11 +23,16 @@ use rustc_macros::HashStable_Generic;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use rustc_macros::{Decodable_Generic, Encodable_Generic};
|
use rustc_macros::{Decodable_Generic, Encodable_Generic};
|
||||||
|
|
||||||
|
mod callconv;
|
||||||
mod layout;
|
mod layout;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use layout::{LayoutCalculator, LayoutCalculatorError};
|
pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
|
||||||
|
pub use layout::{
|
||||||
|
FIRST_VARIANT, FieldIdx, Layout, LayoutCalculator, LayoutCalculatorError, TyAbiInterface,
|
||||||
|
TyAndLayout, VariantIdx,
|
||||||
|
};
|
||||||
|
|
||||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||||
|
|
|
@ -140,7 +140,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> {
|
fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> {
|
||||||
self.iter().filter_map(move |(k, v)| f(k, &*v)).collect()
|
self.iter().filter_map(move |(k, v)| f(k, v)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation
|
/// Find leaked allocations, remove them from memory and return them. Allocations reachable from
|
||||||
/// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true.
|
/// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose
|
||||||
pub fn find_leaked_allocations(
|
/// kind's `may_leak()` returns true.
|
||||||
&self,
|
///
|
||||||
static_roots: &[AllocId],
|
/// This is highly destructive, no more execution can happen after this!
|
||||||
|
pub fn take_leaked_allocations(
|
||||||
|
&mut self,
|
||||||
|
static_roots: impl FnOnce(&Self) -> &[AllocId],
|
||||||
) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)>
|
) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)>
|
||||||
{
|
{
|
||||||
// Collect the set of allocations that are *reachable* from `Global` allocations.
|
// Collect the set of allocations that are *reachable* from `Global` allocations.
|
||||||
|
@ -1008,7 +1011,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
|
self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
|
||||||
if Some(kind) == global_kind { Some(id) } else { None }
|
if Some(kind) == global_kind { Some(id) } else { None }
|
||||||
});
|
});
|
||||||
todo.extend(static_roots);
|
todo.extend(static_roots(self));
|
||||||
while let Some(id) = todo.pop() {
|
while let Some(id) = todo.pop() {
|
||||||
if reachable.insert(id) {
|
if reachable.insert(id) {
|
||||||
// This is a new allocation, add the allocation it points to `todo`.
|
// This is a new allocation, add the allocation it points to `todo`.
|
||||||
|
@ -1023,13 +1026,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
|
// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
|
||||||
self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| {
|
let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| {
|
||||||
if kind.may_leak() || reachable.contains(id) {
|
if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
|
||||||
None
|
});
|
||||||
} else {
|
let mut result = Vec::new();
|
||||||
Some((*id, *kind, alloc.clone()))
|
for &id in leaked.iter() {
|
||||||
}
|
let (kind, alloc) = self.memory.alloc_map.remove(&id).unwrap();
|
||||||
})
|
result.push((id, kind, alloc));
|
||||||
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
|
/// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
|
||||||
|
|
|
@ -301,9 +301,13 @@ fn did_has_local_parent(
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod)
|
peel_parent_while(tcx, parent_did, |tcx, did| {
|
||||||
.map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent)
|
tcx.def_kind(did) == DefKind::Mod
|
||||||
.unwrap_or(false)
|
|| (tcx.def_kind(did) == DefKind::Const
|
||||||
|
&& tcx.opt_item_name(did) == Some(kw::Underscore))
|
||||||
|
})
|
||||||
|
.map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent)
|
||||||
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue
|
/// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue
|
||||||
|
|
|
@ -12,6 +12,7 @@ use std::marker::PhantomData;
|
||||||
use std::ops::{Bound, Deref};
|
use std::ops::{Bound, Deref};
|
||||||
use std::{fmt, iter, mem};
|
use std::{fmt, iter, mem};
|
||||||
|
|
||||||
|
use rustc_abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||||
use rustc_ast::{self as ast, attr};
|
use rustc_ast::{self as ast, attr};
|
||||||
use rustc_data_structures::defer;
|
use rustc_data_structures::defer;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
|
@ -48,7 +49,6 @@ use rustc_session::{Limit, MetadataKind, Session};
|
||||||
use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
|
use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
|
||||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use rustc_type_ir::TyKind::*;
|
use rustc_type_ir::TyKind::*;
|
||||||
use rustc_type_ir::fold::TypeFoldable;
|
use rustc_type_ir::fold::TypeFoldable;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
pub use rustc_abi::{Reg, RegKind};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
use crate::abi::{self, Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
use crate::abi::{self, Abi, Align, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
||||||
use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
|
use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
|
||||||
|
|
||||||
mod aarch64;
|
mod aarch64;
|
||||||
|
@ -192,63 +193,6 @@ impl ArgAttributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
|
||||||
pub enum RegKind {
|
|
||||||
Integer,
|
|
||||||
Float,
|
|
||||||
Vector,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
|
||||||
pub struct Reg {
|
|
||||||
pub kind: RegKind,
|
|
||||||
pub size: Size,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! reg_ctor {
|
|
||||||
($name:ident, $kind:ident, $bits:expr) => {
|
|
||||||
pub fn $name() -> Reg {
|
|
||||||
Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Reg {
|
|
||||||
reg_ctor!(i8, Integer, 8);
|
|
||||||
reg_ctor!(i16, Integer, 16);
|
|
||||||
reg_ctor!(i32, Integer, 32);
|
|
||||||
reg_ctor!(i64, Integer, 64);
|
|
||||||
reg_ctor!(i128, Integer, 128);
|
|
||||||
|
|
||||||
reg_ctor!(f32, Float, 32);
|
|
||||||
reg_ctor!(f64, Float, 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Reg {
|
|
||||||
pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
|
|
||||||
let dl = cx.data_layout();
|
|
||||||
match self.kind {
|
|
||||||
RegKind::Integer => match self.size.bits() {
|
|
||||||
1 => dl.i1_align.abi,
|
|
||||||
2..=8 => dl.i8_align.abi,
|
|
||||||
9..=16 => dl.i16_align.abi,
|
|
||||||
17..=32 => dl.i32_align.abi,
|
|
||||||
33..=64 => dl.i64_align.abi,
|
|
||||||
65..=128 => dl.i128_align.abi,
|
|
||||||
_ => panic!("unsupported integer: {self:?}"),
|
|
||||||
},
|
|
||||||
RegKind::Float => match self.size.bits() {
|
|
||||||
16 => dl.f16_align.abi,
|
|
||||||
32 => dl.f32_align.abi,
|
|
||||||
64 => dl.f64_align.abi,
|
|
||||||
128 => dl.f128_align.abi,
|
|
||||||
_ => panic!("unsupported float: {self:?}"),
|
|
||||||
},
|
|
||||||
RegKind::Vector => dl.vector_align(self.size).abi,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An argument passed entirely registers with the
|
/// An argument passed entirely registers with the
|
||||||
/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
|
/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
|
@ -380,195 +324,6 @@ impl CastTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return value from the `homogeneous_aggregate` test function.
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum HomogeneousAggregate {
|
|
||||||
/// Yes, all the "leaf fields" of this struct are passed in the
|
|
||||||
/// same way (specified in the `Reg` value).
|
|
||||||
Homogeneous(Reg),
|
|
||||||
|
|
||||||
/// There are no leaf fields at all.
|
|
||||||
NoData,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error from the `homogeneous_aggregate` test function, indicating
|
|
||||||
/// there are distinct leaf fields passed in different ways,
|
|
||||||
/// or this is uninhabited.
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub struct Heterogeneous;
|
|
||||||
|
|
||||||
impl HomogeneousAggregate {
|
|
||||||
/// If this is a homogeneous aggregate, returns the homogeneous
|
|
||||||
/// unit, else `None`.
|
|
||||||
pub fn unit(self) -> Option<Reg> {
|
|
||||||
match self {
|
|
||||||
HomogeneousAggregate::Homogeneous(reg) => Some(reg),
|
|
||||||
HomogeneousAggregate::NoData => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
|
|
||||||
/// the same `struct`. Only succeeds if only one of them has any data,
|
|
||||||
/// or both units are identical.
|
|
||||||
fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
|
|
||||||
match (self, other) {
|
|
||||||
(x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
|
|
||||||
|
|
||||||
(HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
|
|
||||||
if a != b {
|
|
||||||
return Err(Heterogeneous);
|
|
||||||
}
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|
||||||
/// Returns `true` if this is an aggregate type (including a ScalarPair!)
|
|
||||||
fn is_aggregate(&self) -> bool {
|
|
||||||
match self.abi {
|
|
||||||
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
|
|
||||||
Abi::ScalarPair(..) | Abi::Aggregate { .. } => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `Homogeneous` if this layout is an aggregate containing fields of
|
|
||||||
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
|
|
||||||
/// special-cased in ABIs.
|
|
||||||
///
|
|
||||||
/// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
|
|
||||||
///
|
|
||||||
/// This is public so that it can be used in unit tests, but
|
|
||||||
/// should generally only be relevant to the ABI details of
|
|
||||||
/// specific targets.
|
|
||||||
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
|
|
||||||
where
|
|
||||||
Ty: TyAbiInterface<'a, C> + Copy,
|
|
||||||
{
|
|
||||||
match self.abi {
|
|
||||||
Abi::Uninhabited => Err(Heterogeneous),
|
|
||||||
|
|
||||||
// The primitive for this algorithm.
|
|
||||||
Abi::Scalar(scalar) => {
|
|
||||||
let kind = match scalar.primitive() {
|
|
||||||
abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
|
|
||||||
abi::Float(_) => RegKind::Float,
|
|
||||||
};
|
|
||||||
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
|
|
||||||
}
|
|
||||||
|
|
||||||
Abi::Vector { .. } => {
|
|
||||||
assert!(!self.is_zst());
|
|
||||||
Ok(HomogeneousAggregate::Homogeneous(Reg {
|
|
||||||
kind: RegKind::Vector,
|
|
||||||
size: self.size,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
|
|
||||||
// Helper for computing `homogeneous_aggregate`, allowing a custom
|
|
||||||
// starting offset (used below for handling variants).
|
|
||||||
let from_fields_at =
|
|
||||||
|layout: Self,
|
|
||||||
start: Size|
|
|
||||||
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
|
|
||||||
let is_union = match layout.fields {
|
|
||||||
FieldsShape::Primitive => {
|
|
||||||
unreachable!("aggregates can't have `FieldsShape::Primitive`")
|
|
||||||
}
|
|
||||||
FieldsShape::Array { count, .. } => {
|
|
||||||
assert_eq!(start, Size::ZERO);
|
|
||||||
|
|
||||||
let result = if count > 0 {
|
|
||||||
layout.field(cx, 0).homogeneous_aggregate(cx)?
|
|
||||||
} else {
|
|
||||||
HomogeneousAggregate::NoData
|
|
||||||
};
|
|
||||||
return Ok((result, layout.size));
|
|
||||||
}
|
|
||||||
FieldsShape::Union(_) => true,
|
|
||||||
FieldsShape::Arbitrary { .. } => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut result = HomogeneousAggregate::NoData;
|
|
||||||
let mut total = start;
|
|
||||||
|
|
||||||
for i in 0..layout.fields.count() {
|
|
||||||
let field = layout.field(cx, i);
|
|
||||||
if field.is_1zst() {
|
|
||||||
// No data here and no impact on layout, can be ignored.
|
|
||||||
// (We might be able to also ignore all aligned ZST but that's less clear.)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !is_union && total != layout.fields.offset(i) {
|
|
||||||
// This field isn't just after the previous one we considered, abort.
|
|
||||||
return Err(Heterogeneous);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = result.merge(field.homogeneous_aggregate(cx)?)?;
|
|
||||||
|
|
||||||
// Keep track of the offset (without padding).
|
|
||||||
let size = field.size;
|
|
||||||
if is_union {
|
|
||||||
total = total.max(size);
|
|
||||||
} else {
|
|
||||||
total += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((result, total))
|
|
||||||
};
|
|
||||||
|
|
||||||
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
|
|
||||||
|
|
||||||
match &self.variants {
|
|
||||||
abi::Variants::Single { .. } => {}
|
|
||||||
abi::Variants::Multiple { variants, .. } => {
|
|
||||||
// Treat enum variants like union members.
|
|
||||||
// HACK(eddyb) pretend the `enum` field (discriminant)
|
|
||||||
// is at the start of every variant (otherwise the gap
|
|
||||||
// at the start of all variants would disqualify them).
|
|
||||||
//
|
|
||||||
// NB: for all tagged `enum`s (which include all non-C-like
|
|
||||||
// `enum`s with defined FFI representation), this will
|
|
||||||
// match the homogeneous computation on the equivalent
|
|
||||||
// `struct { tag; union { variant1; ... } }` and/or
|
|
||||||
// `union { struct { tag; variant1; } ... }`
|
|
||||||
// (the offsets of variant fields should be identical
|
|
||||||
// between the two for either to be a homogeneous aggregate).
|
|
||||||
let variant_start = total;
|
|
||||||
for variant_idx in variants.indices() {
|
|
||||||
let (variant_result, variant_total) =
|
|
||||||
from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;
|
|
||||||
|
|
||||||
result = result.merge(variant_result)?;
|
|
||||||
total = total.max(variant_total);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// There needs to be no padding.
|
|
||||||
if total != self.size {
|
|
||||||
Err(Heterogeneous)
|
|
||||||
} else {
|
|
||||||
match result {
|
|
||||||
HomogeneousAggregate::Homogeneous(_) => {
|
|
||||||
assert_ne!(total, Size::ZERO);
|
|
||||||
}
|
|
||||||
HomogeneousAggregate::NoData => {
|
|
||||||
assert_eq!(total, Size::ZERO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Abi::Aggregate { sized: false } => Err(Heterogeneous),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Information about how to pass an argument to,
|
/// Information about how to pass an argument to,
|
||||||
/// or return a value from, a function, under some ABI.
|
/// or return a value from, a function, under some ABI.
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
|
@ -134,3 +134,9 @@ impl ToJson for TargetMetadata {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToJson for rustc_abi::Endian {
|
||||||
|
fn to_json(&self) -> Json {
|
||||||
|
self.as_str().to_json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub mod abi;
|
|
||||||
pub mod asm;
|
pub mod asm;
|
||||||
|
pub mod callconv;
|
||||||
pub mod json;
|
pub mod json;
|
||||||
pub mod spec;
|
pub mod spec;
|
||||||
pub mod target_features;
|
pub mod target_features;
|
||||||
|
@ -30,6 +30,15 @@ pub mod target_features;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
pub mod abi {
|
||||||
|
pub(crate) use Float::*;
|
||||||
|
pub(crate) use Primitive::*;
|
||||||
|
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||||
|
pub use rustc_abi::{Float, *};
|
||||||
|
|
||||||
|
pub use crate::callconv as call;
|
||||||
|
}
|
||||||
|
|
||||||
pub use rustc_abi::HashStableContext;
|
pub use rustc_abi::HashStableContext;
|
||||||
|
|
||||||
/// The name of rustc's own place to organize libraries.
|
/// The name of rustc's own place to organize libraries.
|
||||||
|
|
|
@ -124,11 +124,8 @@
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(const_index_range_slice_index)]
|
#![feature(const_index_range_slice_index)]
|
||||||
#![feature(const_ipv4)]
|
|
||||||
#![feature(const_ipv6)]
|
|
||||||
#![feature(const_likely)]
|
#![feature(const_likely)]
|
||||||
#![feature(const_make_ascii)]
|
#![feature(const_make_ascii)]
|
||||||
#![feature(const_maybe_uninit_assume_init)]
|
|
||||||
#![feature(const_nonnull_new)]
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_num_midpoint)]
|
#![feature(const_num_midpoint)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
|
|
|
@ -913,7 +913,11 @@ impl<T> MaybeUninit<T> {
|
||||||
/// };
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
|
#[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
|
||||||
#[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
|
||||||
|
#[rustc_const_stable(
|
||||||
|
feature = "const_maybe_uninit_assume_init",
|
||||||
|
since = "CURRENT_RUSTC_VERSION"
|
||||||
|
)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const unsafe fn assume_init_mut(&mut self) -> &mut T {
|
pub const unsafe fn assume_init_mut(&mut self) -> &mut T {
|
||||||
// SAFETY: the caller must guarantee that `self` is initialized.
|
// SAFETY: the caller must guarantee that `self` is initialized.
|
||||||
|
@ -999,7 +1003,8 @@ impl<T> MaybeUninit<T> {
|
||||||
///
|
///
|
||||||
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
|
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
|
||||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||||
#[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
|
||||||
|
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
|
pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
|
||||||
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
||||||
|
|
|
@ -295,7 +295,6 @@ impl IpAddr {
|
||||||
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
|
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
|
||||||
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
|
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -348,7 +347,6 @@ impl IpAddr {
|
||||||
/// true
|
/// true
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -600,6 +598,24 @@ impl Ipv4Addr {
|
||||||
self.octets
|
self.octets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an `Ipv4Addr` from a four element byte array.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(ip_from)]
|
||||||
|
/// use std::net::Ipv4Addr;
|
||||||
|
///
|
||||||
|
/// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]);
|
||||||
|
/// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "ip_from", issue = "131360")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr {
|
||||||
|
Ipv4Addr { octets }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
|
/// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
|
||||||
///
|
///
|
||||||
/// This property is defined in _UNIX Network Programming, Second Edition_,
|
/// This property is defined in _UNIX Network Programming, Second Edition_,
|
||||||
|
@ -776,7 +792,6 @@ impl Ipv4Addr {
|
||||||
///
|
///
|
||||||
/// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
|
/// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -813,7 +828,6 @@ impl Ipv4Addr {
|
||||||
/// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
|
/// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
|
||||||
/// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
|
/// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -841,7 +855,6 @@ impl Ipv4Addr {
|
||||||
/// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
|
/// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
|
||||||
/// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
|
/// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -878,7 +891,6 @@ impl Ipv4Addr {
|
||||||
/// // The broadcast address is not considered as reserved for future use by this implementation
|
/// // 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);
|
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1400,6 +1412,34 @@ impl Ipv6Addr {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an `Ipv6Addr` from an eight element 16-bit array.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(ip_from)]
|
||||||
|
/// use std::net::Ipv6Addr;
|
||||||
|
///
|
||||||
|
/// let addr = Ipv6Addr::from_segments([
|
||||||
|
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
|
||||||
|
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
|
||||||
|
/// ]);
|
||||||
|
/// assert_eq!(
|
||||||
|
/// Ipv6Addr::new(
|
||||||
|
/// 0x20d, 0x20c, 0x20b, 0x20a,
|
||||||
|
/// 0x209, 0x208, 0x207, 0x206,
|
||||||
|
/// ),
|
||||||
|
/// addr
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "ip_from", issue = "131360")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr {
|
||||||
|
let [a, b, c, d, e, f, g, h] = segments;
|
||||||
|
Ipv6Addr::new(a, b, c, d, e, f, g, h)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns [`true`] for the special 'unspecified' address (`::`).
|
/// Returns [`true`] for the special 'unspecified' address (`::`).
|
||||||
///
|
///
|
||||||
/// This property is defined in [IETF RFC 4291].
|
/// This property is defined in [IETF RFC 4291].
|
||||||
|
@ -1510,7 +1550,6 @@ impl Ipv6Addr {
|
||||||
///
|
///
|
||||||
/// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
|
/// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1562,7 +1601,6 @@ impl Ipv6Addr {
|
||||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
|
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
|
||||||
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
|
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1591,7 +1629,6 @@ impl Ipv6Addr {
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
|
||||||
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
|
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1643,7 +1680,6 @@ impl Ipv6Addr {
|
||||||
/// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
|
/// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
|
||||||
/// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
|
/// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1668,7 +1704,6 @@ impl Ipv6Addr {
|
||||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
|
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1729,7 +1764,6 @@ impl Ipv6Addr {
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
|
||||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
|
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1758,7 +1792,6 @@ impl Ipv6Addr {
|
||||||
/// );
|
/// );
|
||||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
|
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1818,7 +1851,6 @@ impl Ipv6Addr {
|
||||||
///
|
///
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1932,7 +1964,7 @@ impl Ipv6Addr {
|
||||||
/// use std::net::Ipv6Addr;
|
/// use std::net::Ipv6Addr;
|
||||||
///
|
///
|
||||||
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
|
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
|
||||||
/// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
/// [0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
|
#[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
|
||||||
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
|
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
|
||||||
|
@ -1941,6 +1973,33 @@ impl Ipv6Addr {
|
||||||
pub const fn octets(&self) -> [u8; 16] {
|
pub const fn octets(&self) -> [u8; 16] {
|
||||||
self.octets
|
self.octets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an `Ipv6Addr` from a sixteen element byte array.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(ip_from)]
|
||||||
|
/// use std::net::Ipv6Addr;
|
||||||
|
///
|
||||||
|
/// let addr = Ipv6Addr::from_octets([
|
||||||
|
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
|
||||||
|
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
|
||||||
|
/// ]);
|
||||||
|
/// assert_eq!(
|
||||||
|
/// Ipv6Addr::new(
|
||||||
|
/// 0x1918, 0x1716, 0x1514, 0x1312,
|
||||||
|
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
|
||||||
|
/// ),
|
||||||
|
/// addr
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "ip_from", issue = "131360")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr {
|
||||||
|
Ipv6Addr { octets }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an Ipv6Addr, conforming to the canonical style described by
|
/// Writes an Ipv6Addr, conforming to the canonical style described by
|
||||||
|
@ -2113,15 +2172,13 @@ impl From<[u8; 16]> for Ipv6Addr {
|
||||||
/// use std::net::Ipv6Addr;
|
/// use std::net::Ipv6Addr;
|
||||||
///
|
///
|
||||||
/// let addr = Ipv6Addr::from([
|
/// let addr = Ipv6Addr::from([
|
||||||
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
|
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
|
||||||
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
|
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
|
||||||
/// ]);
|
/// ]);
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Ipv6Addr::new(
|
/// Ipv6Addr::new(
|
||||||
/// 0x1918, 0x1716,
|
/// 0x1918, 0x1716, 0x1514, 0x1312,
|
||||||
/// 0x1514, 0x1312,
|
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
|
||||||
/// 0x1110, 0x0f0e,
|
|
||||||
/// 0x0d0c, 0x0b0a
|
|
||||||
/// ),
|
/// ),
|
||||||
/// addr
|
/// addr
|
||||||
/// );
|
/// );
|
||||||
|
@ -2142,15 +2199,13 @@ impl From<[u16; 8]> for Ipv6Addr {
|
||||||
/// use std::net::Ipv6Addr;
|
/// use std::net::Ipv6Addr;
|
||||||
///
|
///
|
||||||
/// let addr = Ipv6Addr::from([
|
/// let addr = Ipv6Addr::from([
|
||||||
/// 525u16, 524u16, 523u16, 522u16,
|
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
|
||||||
/// 521u16, 520u16, 519u16, 518u16,
|
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
|
||||||
/// ]);
|
/// ]);
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Ipv6Addr::new(
|
/// Ipv6Addr::new(
|
||||||
/// 0x20d, 0x20c,
|
/// 0x20d, 0x20c, 0x20b, 0x20a,
|
||||||
/// 0x20b, 0x20a,
|
/// 0x209, 0x208, 0x207, 0x206,
|
||||||
/// 0x209, 0x208,
|
|
||||||
/// 0x207, 0x206
|
|
||||||
/// ),
|
/// ),
|
||||||
/// addr
|
/// addr
|
||||||
/// );
|
/// );
|
||||||
|
@ -2172,15 +2227,13 @@ impl From<[u8; 16]> for IpAddr {
|
||||||
/// use std::net::{IpAddr, Ipv6Addr};
|
/// use std::net::{IpAddr, Ipv6Addr};
|
||||||
///
|
///
|
||||||
/// let addr = IpAddr::from([
|
/// let addr = IpAddr::from([
|
||||||
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
|
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
|
||||||
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
|
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
|
||||||
/// ]);
|
/// ]);
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// IpAddr::V6(Ipv6Addr::new(
|
/// IpAddr::V6(Ipv6Addr::new(
|
||||||
/// 0x1918, 0x1716,
|
/// 0x1918, 0x1716, 0x1514, 0x1312,
|
||||||
/// 0x1514, 0x1312,
|
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
|
||||||
/// 0x1110, 0x0f0e,
|
|
||||||
/// 0x0d0c, 0x0b0a
|
|
||||||
/// )),
|
/// )),
|
||||||
/// addr
|
/// addr
|
||||||
/// );
|
/// );
|
||||||
|
@ -2201,15 +2254,13 @@ impl From<[u16; 8]> for IpAddr {
|
||||||
/// use std::net::{IpAddr, Ipv6Addr};
|
/// use std::net::{IpAddr, Ipv6Addr};
|
||||||
///
|
///
|
||||||
/// let addr = IpAddr::from([
|
/// let addr = IpAddr::from([
|
||||||
/// 525u16, 524u16, 523u16, 522u16,
|
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
|
||||||
/// 521u16, 520u16, 519u16, 518u16,
|
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
|
||||||
/// ]);
|
/// ]);
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// IpAddr::V6(Ipv6Addr::new(
|
/// IpAddr::V6(Ipv6Addr::new(
|
||||||
/// 0x20d, 0x20c,
|
/// 0x20d, 0x20c, 0x20b, 0x20a,
|
||||||
/// 0x20b, 0x20a,
|
/// 0x209, 0x208, 0x207, 0x206,
|
||||||
/// 0x209, 0x208,
|
|
||||||
/// 0x207, 0x206
|
|
||||||
/// )),
|
/// )),
|
||||||
/// addr
|
/// addr
|
||||||
/// );
|
/// );
|
||||||
|
|
|
@ -19,9 +19,6 @@
|
||||||
#![feature(const_black_box)]
|
#![feature(const_black_box)]
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(const_ip)]
|
|
||||||
#![feature(const_ipv4)]
|
|
||||||
#![feature(const_ipv6)]
|
|
||||||
#![feature(const_likely)]
|
#![feature(const_likely)]
|
||||||
#![feature(const_nonnull_new)]
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
|
@ -50,6 +47,7 @@
|
||||||
#![feature(hashmap_internals)]
|
#![feature(hashmap_internals)]
|
||||||
#![feature(int_roundings)]
|
#![feature(int_roundings)]
|
||||||
#![feature(ip)]
|
#![feature(ip)]
|
||||||
|
#![feature(ip_from)]
|
||||||
#![feature(is_ascii_octdigit)]
|
#![feature(is_ascii_octdigit)]
|
||||||
#![feature(isqrt)]
|
#![feature(isqrt)]
|
||||||
#![feature(iter_advance_by)]
|
#![feature(iter_advance_by)]
|
||||||
|
|
|
@ -494,6 +494,7 @@ fn ipv6_properties() {
|
||||||
let octets = &[$($octet),*];
|
let octets = &[$($octet),*];
|
||||||
assert_eq!(&ip!($s).octets(), octets);
|
assert_eq!(&ip!($s).octets(), octets);
|
||||||
assert_eq!(Ipv6Addr::from(*octets), ip!($s));
|
assert_eq!(Ipv6Addr::from(*octets), ip!($s));
|
||||||
|
assert_eq!(Ipv6Addr::from_octets(*octets), ip!($s));
|
||||||
|
|
||||||
let unspecified: u32 = 1 << 0;
|
let unspecified: u32 = 1 << 0;
|
||||||
let loopback: u32 = 1 << 1;
|
let loopback: u32 = 1 << 1;
|
||||||
|
@ -846,15 +847,19 @@ fn ipv6_from_constructors() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ipv4_from_octets() {
|
fn ipv4_from_octets() {
|
||||||
assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
|
assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1));
|
||||||
|
assert_eq!(Ipv4Addr::from_octets([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ipv6_from_segments() {
|
fn ipv6_from_segments() {
|
||||||
let from_u16s =
|
let from_u16s =
|
||||||
Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
|
Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
|
||||||
|
let from_u16s_explicit =
|
||||||
|
Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
|
||||||
let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
|
let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
|
||||||
assert_eq!(new, from_u16s);
|
assert_eq!(new, from_u16s);
|
||||||
|
assert_eq!(new, from_u16s_explicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -865,7 +870,15 @@ fn ipv6_from_octets() {
|
||||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
|
||||||
0xff,
|
0xff,
|
||||||
]);
|
]);
|
||||||
|
let from_u16s_explicit =
|
||||||
|
Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
|
||||||
|
let from_u8s_explicit = Ipv6Addr::from_octets([
|
||||||
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
|
||||||
|
0xff,
|
||||||
|
]);
|
||||||
assert_eq!(from_u16s, from_u8s);
|
assert_eq!(from_u16s, from_u8s);
|
||||||
|
assert_eq!(from_u16s, from_u16s_explicit);
|
||||||
|
assert_eq!(from_u16s_explicit, from_u8s_explicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -915,6 +928,9 @@ fn ipv4_const() {
|
||||||
const OCTETS: [u8; 4] = IP_ADDRESS.octets();
|
const OCTETS: [u8; 4] = IP_ADDRESS.octets();
|
||||||
assert_eq!(OCTETS, [127, 0, 0, 1]);
|
assert_eq!(OCTETS, [127, 0, 0, 1]);
|
||||||
|
|
||||||
|
const FROM_OCTETS: Ipv4Addr = Ipv4Addr::from_octets(OCTETS);
|
||||||
|
assert_eq!(IP_ADDRESS, FROM_OCTETS);
|
||||||
|
|
||||||
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
|
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
|
||||||
assert!(!IS_UNSPECIFIED);
|
assert!(!IS_UNSPECIFIED);
|
||||||
|
|
||||||
|
@ -971,9 +987,15 @@ fn ipv6_const() {
|
||||||
const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
|
const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
|
||||||
assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
|
assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
|
||||||
|
const FROM_SEGMENTS: Ipv6Addr = Ipv6Addr::from_segments(SEGMENTS);
|
||||||
|
assert_eq!(IP_ADDRESS, FROM_SEGMENTS);
|
||||||
|
|
||||||
const OCTETS: [u8; 16] = IP_ADDRESS.octets();
|
const OCTETS: [u8; 16] = IP_ADDRESS.octets();
|
||||||
assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
|
assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
|
||||||
|
const FROM_OCTETS: Ipv6Addr = Ipv6Addr::from_octets(OCTETS);
|
||||||
|
assert_eq!(IP_ADDRESS, FROM_OCTETS);
|
||||||
|
|
||||||
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
|
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
|
||||||
assert!(!IS_UNSPECIFIED);
|
assert!(!IS_UNSPECIFIED);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
|
||||||
addr2line = { version = "0.22.0", optional = true, default-features = false }
|
addr2line = { version = "0.22.0", optional = true, default-features = false }
|
||||||
|
|
||||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||||
libc = { version = "0.2.156", default-features = false, features = [
|
libc = { version = "0.2.159", default-features = false, features = [
|
||||||
'rustc-dep-of-std',
|
'rustc-dep-of-std',
|
||||||
], public = true }
|
], public = true }
|
||||||
|
|
||||||
|
|
|
@ -414,9 +414,6 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![feature(const_collections_with_hasher)]
|
#![feature(const_collections_with_hasher)]
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_ip)]
|
|
||||||
#![feature(const_ipv4)]
|
|
||||||
#![feature(const_ipv6)]
|
|
||||||
#![feature(thread_local_internals)]
|
#![feature(thread_local_internals)]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
//
|
//
|
||||||
|
|
|
@ -1538,7 +1538,7 @@ impl fmt::Debug for File {
|
||||||
Some(PathBuf::from(OsString::from_vec(buf)))
|
Some(PathBuf::from(OsString::from_vec(buf)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
|
#[cfg(target_os = "freebsd")]
|
||||||
fn get_path(fd: c_int) -> Option<PathBuf> {
|
fn get_path(fd: c_int) -> Option<PathBuf> {
|
||||||
let info = Box::<libc::kinfo_file>::new_zeroed();
|
let info = Box::<libc::kinfo_file>::new_zeroed();
|
||||||
let mut info = unsafe { info.assume_init() };
|
let mut info = unsafe { info.assume_init() };
|
||||||
|
@ -1566,7 +1566,7 @@ impl fmt::Debug for File {
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "vxworks",
|
target_os = "vxworks",
|
||||||
all(target_os = "freebsd", target_arch = "x86_64"),
|
target_os = "freebsd",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
target_os = "solaris",
|
target_os = "solaris",
|
||||||
|
|
|
@ -20,5 +20,5 @@ exit 1
|
||||||
|
|
||||||
git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable
|
git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable
|
||||||
cd /emsdk-portable
|
cd /emsdk-portable
|
||||||
hide_output ./emsdk install 2.0.5
|
hide_output ./emsdk install 3.1.68
|
||||||
./emsdk activate 2.0.5
|
./emsdk activate 3.1.68
|
||||||
|
|
|
@ -473,14 +473,14 @@ pub fn report_leaks<'tcx>(
|
||||||
leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>, MiriAllocBytes>)>,
|
leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>, MiriAllocBytes>)>,
|
||||||
) {
|
) {
|
||||||
let mut any_pruned = false;
|
let mut any_pruned = false;
|
||||||
for (id, kind, mut alloc) in leaks {
|
for (id, kind, alloc) in leaks {
|
||||||
let mut title = format!(
|
let mut title = format!(
|
||||||
"memory leaked: {id:?} ({}, size: {:?}, align: {:?})",
|
"memory leaked: {id:?} ({}, size: {:?}, align: {:?})",
|
||||||
kind,
|
kind,
|
||||||
alloc.size().bytes(),
|
alloc.size().bytes(),
|
||||||
alloc.align.bytes()
|
alloc.align.bytes()
|
||||||
);
|
);
|
||||||
let Some(backtrace) = alloc.extra.backtrace.take() else {
|
let Some(backtrace) = alloc.extra.backtrace else {
|
||||||
ecx.tcx.dcx().err(title);
|
ecx.tcx.dcx().err(title);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -476,7 +476,7 @@ pub fn eval_entry<'tcx>(
|
||||||
}
|
}
|
||||||
// Check for memory leaks.
|
// Check for memory leaks.
|
||||||
info!("Additional static roots: {:?}", ecx.machine.static_roots);
|
info!("Additional static roots: {:?}", ecx.machine.static_roots);
|
||||||
let leaks = ecx.find_leaked_allocations(&ecx.machine.static_roots);
|
let leaks = ecx.take_leaked_allocations(|ecx| &ecx.machine.static_roots);
|
||||||
if !leaks.is_empty() {
|
if !leaks.is_empty() {
|
||||||
report_leaks(&ecx, leaks);
|
report_leaks(&ecx, leaks);
|
||||||
tcx.dcx().note("set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check");
|
tcx.dcx().note("set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check");
|
||||||
|
|
|
@ -321,7 +321,7 @@ impl ProvenanceExtra {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extra per-allocation data
|
/// Extra per-allocation data
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct AllocExtra<'tcx> {
|
pub struct AllocExtra<'tcx> {
|
||||||
/// Global state of the borrow tracker, if enabled.
|
/// Global state of the borrow tracker, if enabled.
|
||||||
pub borrow_tracker: Option<borrow_tracker::AllocState>,
|
pub borrow_tracker: Option<borrow_tracker::AllocState>,
|
||||||
|
@ -338,6 +338,14 @@ pub struct AllocExtra<'tcx> {
|
||||||
pub backtrace: Option<Vec<FrameInfo<'tcx>>>,
|
pub backtrace: Option<Vec<FrameInfo<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need a `Clone` impl because the machine passes `Allocation` through `Cow`...
|
||||||
|
// but that should never end up actually cloning our `AllocExtra`.
|
||||||
|
impl<'tcx> Clone for AllocExtra<'tcx> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
panic!("our allocations should never be cloned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl VisitProvenance for AllocExtra<'_> {
|
impl VisitProvenance for AllocExtra<'_> {
|
||||||
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
|
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
|
||||||
let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self;
|
let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self;
|
||||||
|
|
|
@ -31,4 +31,15 @@ const _: () = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/131643
|
||||||
|
const _: () = {
|
||||||
|
const _: () = {
|
||||||
|
impl tmp::InnerTest {}
|
||||||
|
};
|
||||||
|
|
||||||
|
mod tmp {
|
||||||
|
pub(super) struct InnerTest;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -21,4 +21,13 @@ const _: () = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/131643
|
||||||
|
const _: () = {
|
||||||
|
const _: () = {
|
||||||
|
impl InnerTest {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InnerTest;
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue