1
Fork 0

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:
bors 2024-10-14 12:20:35 +00:00
commit 17a19e684c
49 changed files with 469 additions and 338 deletions

View 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),
}
}
}

View file

@ -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).

View file

@ -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.

View file

@ -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

View file

@ -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)]

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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)]

View file

@ -134,3 +134,9 @@ impl ToJson for TargetMetadata {
}) })
} }
} }
impl ToJson for rustc_abi::Endian {
fn to_json(&self) -> Json {
self.as_str().to_json()
}
}

View file

@ -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.

View file

@ -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)]

View file

@ -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

View file

@ -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
/// ); /// );

View file

@ -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)]

View file

@ -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);

View file

@ -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 }

View file

@ -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
// //

View file

@ -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",

View file

@ -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

View file

@ -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;
}; };

View file

@ -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");

View file

@ -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;

View file

@ -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() {}

View file

@ -21,4 +21,13 @@ const _: () = {
}; };
}; };
// https://github.com/rust-lang/rust/issues/131643
const _: () = {
const _: () = {
impl InnerTest {}
};
struct InnerTest;
};
fn main() {} fn main() {}