mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
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
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,
|
||||
};
|
||||
|
||||
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.
|
||||
// Present uninhabited variants only require space for their fields,
|
||||
// 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_macros::HashStable_Generic;
|
||||
|
||||
use crate::json::{Json, ToJson};
|
||||
|
||||
pub mod call;
|
||||
|
||||
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||
pub use rustc_abi::{Float, *};
|
||||
|
||||
impl ToJson for Endian {
|
||||
fn to_json(&self) -> Json {
|
||||
self.as_str().to_json()
|
||||
}
|
||||
}
|
||||
use crate::{Float, *};
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a field in a variant.
|
@ -1,6 +1,7 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
#![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(step_trait))]
|
||||
#![warn(unreachable_pub)]
|
||||
@ -22,11 +23,16 @@ use rustc_macros::HashStable_Generic;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable_Generic, Encodable_Generic};
|
||||
|
||||
mod callconv;
|
||||
mod layout;
|
||||
#[cfg(test)]
|
||||
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.
|
||||
/// 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)]
|
||||
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)]
|
||||
|
@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
bytes
|
||||
}
|
||||
|
||||
/// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation
|
||||
/// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true.
|
||||
pub fn find_leaked_allocations(
|
||||
&self,
|
||||
static_roots: &[AllocId],
|
||||
/// Find leaked allocations, remove them from memory and return them. Allocations reachable from
|
||||
/// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose
|
||||
/// kind's `may_leak()` returns true.
|
||||
///
|
||||
/// 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>)>
|
||||
{
|
||||
// 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, _)| {
|
||||
if Some(kind) == global_kind { Some(id) } else { None }
|
||||
});
|
||||
todo.extend(static_roots);
|
||||
todo.extend(static_roots(self));
|
||||
while let Some(id) = todo.pop() {
|
||||
if reachable.insert(id) {
|
||||
// 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.
|
||||
self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| {
|
||||
if kind.may_leak() || reachable.contains(id) {
|
||||
None
|
||||
} else {
|
||||
Some((*id, *kind, alloc.clone()))
|
||||
}
|
||||
})
|
||||
let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| {
|
||||
if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
|
||||
});
|
||||
let mut result = Vec::new();
|
||||
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
|
||||
|
@ -301,9 +301,13 @@ fn did_has_local_parent(
|
||||
return false;
|
||||
};
|
||||
|
||||
peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod)
|
||||
.map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent)
|
||||
.unwrap_or(false)
|
||||
peel_parent_while(tcx, parent_did, |tcx, did| {
|
||||
tcx.def_kind(did) == DefKind::Mod
|
||||
|| (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
|
||||
|
@ -12,6 +12,7 @@ use std::marker::PhantomData;
|
||||
use std::ops::{Bound, Deref};
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use rustc_abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||
use rustc_ast::{self as ast, attr};
|
||||
use rustc_data_structures::defer;
|
||||
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::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_type_ir::TyKind::*;
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
|
@ -1,10 +1,11 @@
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use rustc_abi::{Reg, RegKind};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
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};
|
||||
|
||||
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
|
||||
/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
|
||||
#[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,
|
||||
/// or return a value from, a function, under some ABI.
|
||||
#[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};
|
||||
|
||||
pub mod abi;
|
||||
pub mod asm;
|
||||
pub mod callconv;
|
||||
pub mod json;
|
||||
pub mod spec;
|
||||
pub mod target_features;
|
||||
@ -30,6 +30,15 @@ pub mod target_features;
|
||||
#[cfg(test)]
|
||||
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;
|
||||
|
||||
/// The name of rustc's own place to organize libraries.
|
||||
|
@ -124,11 +124,8 @@
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_index_range_slice_index)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(const_likely)]
|
||||
#![feature(const_make_ascii)]
|
||||
#![feature(const_maybe_uninit_assume_init)]
|
||||
#![feature(const_nonnull_new)]
|
||||
#![feature(const_num_midpoint)]
|
||||
#![feature(const_option_ext)]
|
||||
|
@ -913,7 +913,11 @@ impl<T> MaybeUninit<T> {
|
||||
/// };
|
||||
/// ```
|
||||
#[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)]
|
||||
pub const unsafe fn assume_init_mut(&mut self) -> &mut T {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized.
|
||||
@ -999,7 +1003,8 @@ impl<T> MaybeUninit<T> {
|
||||
///
|
||||
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
|
||||
#[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)]
|
||||
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
|
||||
|
@ -295,7 +295,6 @@ impl IpAddr {
|
||||
/// 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);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -348,7 +347,6 @@ impl IpAddr {
|
||||
/// true
|
||||
/// );
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -600,6 +598,24 @@ impl Ipv4Addr {
|
||||
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`).
|
||||
///
|
||||
/// 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.
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -813,7 +828,6 @@ impl Ipv4Addr {
|
||||
/// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
|
||||
/// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -841,7 +855,6 @@ impl Ipv4Addr {
|
||||
/// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
|
||||
/// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -878,7 +891,6 @@ 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);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[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 (`::`).
|
||||
///
|
||||
/// 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.
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[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(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")]
|
||||
#[must_use]
|
||||
#[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(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[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(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")]
|
||||
#[must_use]
|
||||
#[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(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[must_use]
|
||||
#[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(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")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -1758,7 +1792,6 @@ impl Ipv6Addr {
|
||||
/// );
|
||||
/// 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")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -1818,7 +1851,6 @@ impl Ipv6Addr {
|
||||
///
|
||||
/// 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")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
@ -1932,7 +1964,7 @@ impl Ipv6Addr {
|
||||
/// use std::net::Ipv6Addr;
|
||||
///
|
||||
/// 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")]
|
||||
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
|
||||
@ -1941,6 +1973,33 @@ impl Ipv6Addr {
|
||||
pub const fn octets(&self) -> [u8; 16] {
|
||||
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
|
||||
@ -2113,15 +2172,13 @@ impl From<[u8; 16]> for Ipv6Addr {
|
||||
/// use std::net::Ipv6Addr;
|
||||
///
|
||||
/// let addr = Ipv6Addr::from([
|
||||
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
|
||||
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
|
||||
/// 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
|
||||
/// 0x1918, 0x1716, 0x1514, 0x1312,
|
||||
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
|
||||
/// ),
|
||||
/// addr
|
||||
/// );
|
||||
@ -2142,15 +2199,13 @@ impl From<[u16; 8]> for Ipv6Addr {
|
||||
/// use std::net::Ipv6Addr;
|
||||
///
|
||||
/// let addr = Ipv6Addr::from([
|
||||
/// 525u16, 524u16, 523u16, 522u16,
|
||||
/// 521u16, 520u16, 519u16, 518u16,
|
||||
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
|
||||
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
|
||||
/// ]);
|
||||
/// assert_eq!(
|
||||
/// Ipv6Addr::new(
|
||||
/// 0x20d, 0x20c,
|
||||
/// 0x20b, 0x20a,
|
||||
/// 0x209, 0x208,
|
||||
/// 0x207, 0x206
|
||||
/// 0x20d, 0x20c, 0x20b, 0x20a,
|
||||
/// 0x209, 0x208, 0x207, 0x206,
|
||||
/// ),
|
||||
/// addr
|
||||
/// );
|
||||
@ -2172,15 +2227,13 @@ impl From<[u8; 16]> for IpAddr {
|
||||
/// use std::net::{IpAddr, Ipv6Addr};
|
||||
///
|
||||
/// let addr = IpAddr::from([
|
||||
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
|
||||
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
|
||||
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
|
||||
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
|
||||
/// ]);
|
||||
/// assert_eq!(
|
||||
/// IpAddr::V6(Ipv6Addr::new(
|
||||
/// 0x1918, 0x1716,
|
||||
/// 0x1514, 0x1312,
|
||||
/// 0x1110, 0x0f0e,
|
||||
/// 0x0d0c, 0x0b0a
|
||||
/// 0x1918, 0x1716, 0x1514, 0x1312,
|
||||
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
|
||||
/// )),
|
||||
/// addr
|
||||
/// );
|
||||
@ -2201,15 +2254,13 @@ impl From<[u16; 8]> for IpAddr {
|
||||
/// use std::net::{IpAddr, Ipv6Addr};
|
||||
///
|
||||
/// let addr = IpAddr::from([
|
||||
/// 525u16, 524u16, 523u16, 522u16,
|
||||
/// 521u16, 520u16, 519u16, 518u16,
|
||||
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
|
||||
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
|
||||
/// ]);
|
||||
/// assert_eq!(
|
||||
/// IpAddr::V6(Ipv6Addr::new(
|
||||
/// 0x20d, 0x20c,
|
||||
/// 0x20b, 0x20a,
|
||||
/// 0x209, 0x208,
|
||||
/// 0x207, 0x206
|
||||
/// 0x20d, 0x20c, 0x20b, 0x20a,
|
||||
/// 0x209, 0x208, 0x207, 0x206,
|
||||
/// )),
|
||||
/// addr
|
||||
/// );
|
||||
|
@ -19,9 +19,6 @@
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_ip)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(const_likely)]
|
||||
#![feature(const_nonnull_new)]
|
||||
#![feature(const_option_ext)]
|
||||
@ -50,6 +47,7 @@
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(int_roundings)]
|
||||
#![feature(ip)]
|
||||
#![feature(ip_from)]
|
||||
#![feature(is_ascii_octdigit)]
|
||||
#![feature(isqrt)]
|
||||
#![feature(iter_advance_by)]
|
||||
|
@ -494,6 +494,7 @@ fn ipv6_properties() {
|
||||
let octets = &[$($octet),*];
|
||||
assert_eq!(&ip!($s).octets(), octets);
|
||||
assert_eq!(Ipv6Addr::from(*octets), ip!($s));
|
||||
assert_eq!(Ipv6Addr::from_octets(*octets), ip!($s));
|
||||
|
||||
let unspecified: u32 = 1 << 0;
|
||||
let loopback: u32 = 1 << 1;
|
||||
@ -846,15 +847,19 @@ fn ipv6_from_constructors() {
|
||||
|
||||
#[test]
|
||||
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]
|
||||
fn ipv6_from_segments() {
|
||||
let from_u16s =
|
||||
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);
|
||||
assert_eq!(new, from_u16s);
|
||||
assert_eq!(new, from_u16s_explicit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -865,7 +870,15 @@ fn ipv6_from_octets() {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
|
||||
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_u16s_explicit);
|
||||
assert_eq!(from_u16s_explicit, from_u8s_explicit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -915,6 +928,9 @@ fn ipv4_const() {
|
||||
const OCTETS: [u8; 4] = IP_ADDRESS.octets();
|
||||
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();
|
||||
assert!(!IS_UNSPECIFIED);
|
||||
|
||||
@ -971,9 +987,15 @@ fn ipv6_const() {
|
||||
const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
|
||||
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();
|
||||
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();
|
||||
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 }
|
||||
|
||||
[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',
|
||||
], public = true }
|
||||
|
||||
|
@ -414,9 +414,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![feature(const_collections_with_hasher)]
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_ip)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(thread_local_internals)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
|
@ -1538,7 +1538,7 @@ impl fmt::Debug for File {
|
||||
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> {
|
||||
let info = Box::<libc::kinfo_file>::new_zeroed();
|
||||
let mut info = unsafe { info.assume_init() };
|
||||
@ -1566,7 +1566,7 @@ impl fmt::Debug for File {
|
||||
#[cfg(not(any(
|
||||
target_os = "linux",
|
||||
target_os = "vxworks",
|
||||
all(target_os = "freebsd", target_arch = "x86_64"),
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "illumos",
|
||||
target_os = "solaris",
|
||||
|
@ -20,5 +20,5 @@ exit 1
|
||||
|
||||
git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable
|
||||
cd /emsdk-portable
|
||||
hide_output ./emsdk install 2.0.5
|
||||
./emsdk activate 2.0.5
|
||||
hide_output ./emsdk install 3.1.68
|
||||
./emsdk activate 3.1.68
|
||||
|
@ -473,14 +473,14 @@ pub fn report_leaks<'tcx>(
|
||||
leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>, MiriAllocBytes>)>,
|
||||
) {
|
||||
let mut any_pruned = false;
|
||||
for (id, kind, mut alloc) in leaks {
|
||||
for (id, kind, alloc) in leaks {
|
||||
let mut title = format!(
|
||||
"memory leaked: {id:?} ({}, size: {:?}, align: {:?})",
|
||||
kind,
|
||||
alloc.size().bytes(),
|
||||
alloc.align.bytes()
|
||||
);
|
||||
let Some(backtrace) = alloc.extra.backtrace.take() else {
|
||||
let Some(backtrace) = alloc.extra.backtrace else {
|
||||
ecx.tcx.dcx().err(title);
|
||||
continue;
|
||||
};
|
||||
|
@ -476,7 +476,7 @@ pub fn eval_entry<'tcx>(
|
||||
}
|
||||
// Check for memory leaks.
|
||||
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() {
|
||||
report_leaks(&ecx, leaks);
|
||||
tcx.dcx().note("set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check");
|
||||
|
@ -321,7 +321,7 @@ impl ProvenanceExtra {
|
||||
}
|
||||
|
||||
/// Extra per-allocation data
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
pub struct AllocExtra<'tcx> {
|
||||
/// Global state of the borrow tracker, if enabled.
|
||||
pub borrow_tracker: Option<borrow_tracker::AllocState>,
|
||||
@ -338,6 +338,14 @@ pub struct AllocExtra<'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<'_> {
|
||||
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
|
||||
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() {}
|
||||
|
@ -21,4 +21,13 @@ const _: () = {
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/131643
|
||||
const _: () = {
|
||||
const _: () = {
|
||||
impl InnerTest {}
|
||||
};
|
||||
|
||||
struct InnerTest;
|
||||
};
|
||||
|
||||
fn main() {}
|
||||
|
Loading…
Reference in New Issue
Block a user