1
Fork 0

Auto merge of #136534 - jhpratt:rollup-dnz57dq, r=jhpratt

Rollup of 6 pull requests

Successful merges:

 - #136398 (add UnsafeCell direct access APIs)
 - #136465 (Some `rustc_middle` cleanups)
 - #136479 (std::fs: further simplify dirent64 handling)
 - #136504 (Fix last compare-mode false negatives in tests)
 - #136511 (Add `cast_signed` and `cast_unsigned` methods for `NonZero` types)
 - #136518 (Add note about `FnPtr` trait being exposed as public bound)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-02-04 14:59:25 +00:00
commit 01e4f19cc8
21 changed files with 242 additions and 170 deletions

View file

@ -1,61 +1,3 @@
//! Nodes in the dependency graph.
//!
//! A node in the [dependency graph] is represented by a [`DepNode`].
//! A `DepNode` consists of a [`DepKind`] (which
//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.)
//! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which
//! depends on the node's `DepKind`. Together, the kind and the fingerprint
//! fully identify a dependency node, even across multiple compilation sessions.
//! In other words, the value of the fingerprint does not depend on anything
//! that is specific to a given compilation session, like an unpredictable
//! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a
//! pointer. The concept behind this could be compared to how git commit hashes
//! uniquely identify a given commit. The fingerprinting approach has
//! a few advantages:
//!
//! * A `DepNode` can simply be serialized to disk and loaded in another session
//! without the need to do any "rebasing" (like we have to do for Spans and
//! NodeIds) or "retracing" (like we had to do for `DefId` in earlier
//! implementations of the dependency graph).
//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to
//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc.
//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into
//! memory without any post-processing (e.g., "abomination-style" pointer
//! reconstruction).
//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that
//! refer to things that do not exist anymore. In previous implementations
//! `DepNode` contained a `DefId`. A `DepNode` referring to something that
//! had been removed between the previous and the current compilation session
//! could not be instantiated because the current compilation session
//! contained no `DefId` for thing that had been removed.
//!
//! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro
//! defines the `DepKind` enum. Each `DepKind` has its own parameters that are
//! needed at runtime in order to construct a valid `DepNode` fingerprint.
//! However, only `CompileCodegenUnit` and `CompileMonoItem` are constructed
//! explicitly (with `make_compile_codegen_unit` cq `make_compile_mono_item`).
//!
//! Because the macro sees what parameters a given `DepKind` requires, it can
//! "infer" some properties for each kind of `DepNode`:
//!
//! * Whether a `DepNode` of a given kind has any parameters at all. Some
//! `DepNode`s could represent global concepts with only one value.
//! * Whether it is possible, in principle, to reconstruct a query key from a
//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter,
//! in which case it is possible to map the node's fingerprint back to the
//! `DefId` it was computed from. In other cases, too much information gets
//! lost during fingerprint computation.
//!
//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with
//! `DepNode::new()`, ensures that only valid `DepNode` instances can be
//! constructed. For example, the API does not allow for constructing
//! parameterless `DepNode`s with anything other than a zeroed out fingerprint.
//! More generally speaking, it relieves the user of the `DepNode` API of
//! having to know how to compute the expected fingerprint for a given set of
//! node parameters.
//!
//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
use rustc_hir::definitions::DefPathHash; use rustc_hir::definitions::DefPathHash;
@ -158,26 +100,14 @@ pub(crate) fn make_compile_mono_item<'tcx>(
} }
pub trait DepNodeExt: Sized { pub trait DepNodeExt: Sized {
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
///
/// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
/// 2. the item that the DefPath refers to exists in the current tcx.
///
/// Condition (1) is determined by the DepKind variant of the
/// DepNode. Condition (2) might not be fulfilled if a DepNode
/// refers to something from the previous compilation session that
/// has been removed.
fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>; fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
/// Used in testing
fn from_label_string( fn from_label_string(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
label: &str, label: &str,
def_path_hash: DefPathHash, def_path_hash: DefPathHash,
) -> Result<Self, ()>; ) -> Result<Self, ()>;
/// Used in testing
fn has_label_string(label: &str) -> bool; fn has_label_string(label: &str) -> bool;
} }
@ -399,52 +329,46 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
} }
} }
macro_rules! impl_for_typed_def_id { impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for ModDefId {
($Name:ident, $LocalName:ident) => { #[inline(always)]
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for $Name { fn fingerprint_style() -> FingerprintStyle {
#[inline(always)] FingerprintStyle::DefPathHash
fn fingerprint_style() -> FingerprintStyle { }
FingerprintStyle::DefPathHash
}
#[inline(always)] #[inline(always)]
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
self.to_def_id().to_fingerprint(tcx) self.to_def_id().to_fingerprint(tcx)
} }
#[inline(always)] #[inline(always)]
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
self.to_def_id().to_debug_str(tcx) self.to_def_id().to_debug_str(tcx)
} }
#[inline(always)] #[inline(always)]
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
DefId::recover(tcx, dep_node).map($Name::new_unchecked) DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked)
} }
}
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for $LocalName {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
}
#[inline(always)]
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
self.to_def_id().to_fingerprint(tcx)
}
#[inline(always)]
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
self.to_def_id().to_debug_str(tcx)
}
#[inline(always)]
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
LocalDefId::recover(tcx, dep_node).map($LocalName::new_unchecked)
}
}
};
} }
impl_for_typed_def_id! { ModDefId, LocalModDefId } impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalModDefId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
FingerprintStyle::DefPathHash
}
#[inline(always)]
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
self.to_def_id().to_fingerprint(tcx)
}
#[inline(always)]
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
self.to_def_id().to_debug_str(tcx)
}
#[inline(always)]
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked)
}
}

View file

@ -1,10 +1,11 @@
//! The "main crate" of the Rust compiler. This crate contains common //! The "main crate" of the Rust compiler. This crate contains common
//! type definitions that are used by the other crates in the rustc //! type definitions that are used by the other crates in the rustc
//! "family". Some prominent examples (note that each of these modules //! "family". The following are some prominent examples.
//! has their own README with further details).
//! //!
//! - **HIR.** The "high-level (H) intermediate representation (IR)" is //! - **HIR.** The "high-level (H) intermediate representation (IR)" is
//! defined in the [`hir`] module. //! defined in the [`hir`] module.
//! - **THIR.** The "typed high-level (H) intermediate representation (IR)"
//! is defined in the [`thir`] module.
//! - **MIR.** The "mid-level (M) intermediate representation (IR)" is //! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
//! defined in the [`mir`] module. This module contains only the //! defined in the [`mir`] module. This module contains only the
//! *definition* of the MIR; the passes that transform and operate //! *definition* of the MIR; the passes that transform and operate
@ -37,7 +38,6 @@
#![feature(box_as_ptr)] #![feature(box_as_ptr)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(closure_track_caller)] #![feature(closure_track_caller)]
#![feature(const_type_name)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(coroutines)] #![feature(coroutines)]
#![feature(debug_closure_helpers)] #![feature(debug_closure_helpers)]
@ -50,7 +50,6 @@
#![feature(intra_doc_pointers)] #![feature(intra_doc_pointers)]
#![feature(iter_from_coroutine)] #![feature(iter_from_coroutine)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(negative_impls)] #![feature(negative_impls)]
#![feature(never_type)] #![feature(never_type)]

View file

@ -37,9 +37,6 @@ pub mod visit;
macro_rules! thir_with_elements { macro_rules! thir_with_elements {
( (
$($field_name:ident: $field_ty:ty,)*
@elements:
$($name:ident: $id:ty => $value:ty => $format:literal,)* $($name:ident: $id:ty => $value:ty => $format:literal,)*
) => { ) => {
$( $(
@ -55,20 +52,16 @@ macro_rules! thir_with_elements {
/// This can be indexed directly by any THIR index (e.g. [`ExprId`]). /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
#[derive(Debug, HashStable)] #[derive(Debug, HashStable)]
pub struct Thir<'tcx> { pub struct Thir<'tcx> {
$( pub body_type: BodyTy<'tcx>,
pub $field_name: $field_ty,
)*
$( $(
pub $name: IndexVec<$id, $value>, pub $name: IndexVec<$id, $value>,
)* )*
} }
impl<'tcx> Thir<'tcx> { impl<'tcx> Thir<'tcx> {
pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> { pub fn new(body_type: BodyTy<'tcx>) -> Thir<'tcx> {
Thir { Thir {
$( body_type,
$field_name,
)*
$( $(
$name: IndexVec::new(), $name: IndexVec::new(),
)* )*
@ -88,9 +81,6 @@ macro_rules! thir_with_elements {
} }
thir_with_elements! { thir_with_elements! {
body_type: BodyTy<'tcx>,
@elements:
arms: ArmId => Arm<'tcx> => "a{}", arms: ArmId => Arm<'tcx> => "a{}",
blocks: BlockId => Block => "b{}", blocks: BlockId => Block => "b{}",
exprs: ExprId => Expr<'tcx> => "e{}", exprs: ExprId => Expr<'tcx> => "e{}",

View file

@ -1,8 +1,7 @@
use super::{ use super::{
AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, Pat, AdtExpr, AdtExprBase, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand,
PatKind, Stmt, StmtKind, Thir, Pat, PatKind, Stmt, StmtKind, Thir,
}; };
use crate::thir::AdtExprBase;
pub trait Visitor<'thir, 'tcx: 'thir>: Sized { pub trait Visitor<'thir, 'tcx: 'thir>: Sized {
fn thir(&self) -> &'thir Thir<'tcx>; fn thir(&self) -> &'thir Thir<'tcx>;

View file

@ -21,13 +21,12 @@ use rustc_macros::{
}; };
use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_span::{DUMMY_SP, Span, Symbol};
// FIXME: Remove this import and import via `solve::`
pub use rustc_type_ir::solve::BuiltinImplSource;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
use thin_vec::ThinVec; use thin_vec::ThinVec;
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
use crate::mir::ConstraintCategory; use crate::mir::ConstraintCategory;
pub use crate::traits::solve::BuiltinImplSource;
use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::abstract_const::NotConstEvaluatable;
use crate::ty::{self, AdtKind, GenericArgsRef, Ty}; use crate::ty::{self, AdtKind, GenericArgsRef, Ty};

View file

@ -7,11 +7,10 @@
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
use rustc_span::Span; use rustc_span::Span;
// FIXME: Remove this import and import via `traits::solve`.
pub use rustc_type_ir::solve::NoSolution;
use crate::error::DropCheckOverflow; use crate::error::DropCheckOverflow;
use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse};
pub use crate::traits::solve::NoSolution;
use crate::ty::{self, GenericArg, Ty, TyCtxt}; use crate::ty::{self, GenericArg, Ty, TyCtxt};
pub mod type_op { pub mod type_op {

View file

@ -1,19 +1,20 @@
//! This module defines the `DepNode` type which the compiler uses to represent //! This module defines the [`DepNode`] type which the compiler uses to represent
//! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which //! nodes in the [dependency graph]. A `DepNode` consists of a [`DepKind`] (which
//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) //! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.)
//! and a `Fingerprint`, a 128 bit hash value the exact meaning of which //! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which
//! depends on the node's `DepKind`. Together, the kind and the fingerprint //! depends on the node's `DepKind`. Together, the kind and the fingerprint
//! fully identify a dependency node, even across multiple compilation sessions. //! fully identify a dependency node, even across multiple compilation sessions.
//! In other words, the value of the fingerprint does not depend on anything //! In other words, the value of the fingerprint does not depend on anything
//! that is specific to a given compilation session, like an unpredictable //! that is specific to a given compilation session, like an unpredictable
//! interning key (e.g., NodeId, DefId, Symbol) or the numeric value of a //! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a
//! pointer. The concept behind this could be compared to how git commit hashes //! pointer. The concept behind this could be compared to how git commit hashes
//! uniquely identify a given commit and has a few advantages: //! uniquely identify a given commit. The fingerprinting approach has
//! a few advantages:
//! //!
//! * A `DepNode` can simply be serialized to disk and loaded in another session //! * A `DepNode` can simply be serialized to disk and loaded in another session
//! without the need to do any "rebasing (like we have to do for Spans and //! without the need to do any "rebasing" (like we have to do for Spans and
//! NodeIds) or "retracing" like we had to do for `DefId` in earlier //! NodeIds) or "retracing" (like we had to do for `DefId` in earlier
//! implementations of the dependency graph. //! implementations of the dependency graph).
//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to
//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. //! implement `Copy`, `Sync`, `Send`, `Freeze`, etc.
//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into
@ -26,10 +27,12 @@
//! could not be instantiated because the current compilation session //! could not be instantiated because the current compilation session
//! contained no `DefId` for thing that had been removed. //! contained no `DefId` for thing that had been removed.
//! //!
//! `DepNode` definition happens in `rustc_middle` with the `define_dep_nodes!()` macro. //! `DepNode` definition happens in `rustc_middle` with the
//! This macro defines the `DepKind` enum and a corresponding `DepConstructor` enum. The //! `define_dep_nodes!()` macro. This macro defines the `DepKind` enum. Each
//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at runtime in order //! `DepKind` has its own parameters that are needed at runtime in order to
//! to construct a valid `DepNode` fingerprint. //! construct a valid `DepNode` fingerprint. However, only `CompileCodegenUnit`
//! and `CompileMonoItem` are constructed explicitly (with
//! `make_compile_codegen_unit` and `make_compile_mono_item`).
//! //!
//! Because the macro sees what parameters a given `DepKind` requires, it can //! Because the macro sees what parameters a given `DepKind` requires, it can
//! "infer" some properties for each kind of `DepNode`: //! "infer" some properties for each kind of `DepNode`:
@ -41,6 +44,16 @@
//! in which case it is possible to map the node's fingerprint back to the //! in which case it is possible to map the node's fingerprint back to the
//! `DefId` it was computed from. In other cases, too much information gets //! `DefId` it was computed from. In other cases, too much information gets
//! lost during fingerprint computation. //! lost during fingerprint computation.
//!
//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with
//! `DepNode::new()`, ensure that only valid `DepNode` instances can be
//! constructed. For example, the API does not allow for constructing
//! parameterless `DepNode`s with anything other than a zeroed out fingerprint.
//! More generally speaking, it relieves the user of the `DepNode` API of
//! having to know how to compute the expected fingerprint for a given set of
//! node parameters.
//!
//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::Hash;

View file

@ -2118,6 +2118,35 @@ impl<T> UnsafeCell<T> {
pub const fn into_inner(self) -> T { pub const fn into_inner(self) -> T {
self.value self.value
} }
/// Replace the value in this `UnsafeCell` and return the old value.
///
/// # Safety
///
/// The caller must take care to avoid aliasing and data races.
///
/// - It is Undefined Behavior to allow calls to race with
/// any other access to the wrapped value.
/// - It is Undefined Behavior to call this while any other
/// reference(s) to the wrapped value are alive.
///
/// # Examples
///
/// ```
/// #![feature(unsafe_cell_access)]
/// use std::cell::UnsafeCell;
///
/// let uc = UnsafeCell::new(5);
///
/// let old = unsafe { uc.replace(10) };
/// assert_eq!(old, 5);
/// ```
#[inline]
#[unstable(feature = "unsafe_cell_access", issue = "136327")]
pub const unsafe fn replace(&self, value: T) -> T {
// SAFETY: pointer comes from `&self` so naturally satisfies invariants.
unsafe { ptr::replace(self.get(), value) }
}
} }
impl<T: ?Sized> UnsafeCell<T> { impl<T: ?Sized> UnsafeCell<T> {
@ -2230,6 +2259,61 @@ impl<T: ?Sized> UnsafeCell<T> {
// no guarantee for user code that this will work in future versions of the compiler! // no guarantee for user code that this will work in future versions of the compiler!
this as *const T as *mut T this as *const T as *mut T
} }
/// Get a shared reference to the value within the `UnsafeCell`.
///
/// # Safety
///
/// - It is Undefined Behavior to call this while any mutable
/// reference to the wrapped value is alive.
/// - Mutating the wrapped value while the returned
/// reference is alive is Undefined Behavior.
///
/// # Examples
///
/// ```
/// #![feature(unsafe_cell_access)]
/// use std::cell::UnsafeCell;
///
/// let uc = UnsafeCell::new(5);
///
/// let val = unsafe { uc.as_ref_unchecked() };
/// assert_eq!(val, &5);
/// ```
#[inline]
#[unstable(feature = "unsafe_cell_access", issue = "136327")]
pub const unsafe fn as_ref_unchecked(&self) -> &T {
// SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
unsafe { self.get().as_ref_unchecked() }
}
/// Get an exclusive reference to the value within the `UnsafeCell`.
///
/// # Safety
///
/// - It is Undefined Behavior to call this while any other
/// reference(s) to the wrapped value are alive.
/// - Mutating the wrapped value through other means while the
/// returned reference is alive is Undefined Behavior.
///
/// # Examples
///
/// ```
/// #![feature(unsafe_cell_access)]
/// use std::cell::UnsafeCell;
///
/// let uc = UnsafeCell::new(5);
///
/// unsafe { *uc.as_mut_unchecked() += 1; }
/// assert_eq!(uc.into_inner(), 6);
/// ```
#[inline]
#[unstable(feature = "unsafe_cell_access", issue = "136327")]
#[allow(clippy::mut_from_ref)]
pub const unsafe fn as_mut_unchecked(&self) -> &mut T {
// SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
unsafe { self.get().as_mut_unchecked() }
}
} }
#[stable(feature = "unsafe_cell_default", since = "1.10.0")] #[stable(feature = "unsafe_cell_default", since = "1.10.0")]

View file

@ -1077,6 +1077,9 @@ marker_impls! {
} }
/// A common trait implemented by all function pointers. /// A common trait implemented by all function pointers.
//
// Note that while the trait is internal and unstable it is nevertheless
// exposed as a public bound of the stable `core::ptr::fn_addr_eq` function.
#[unstable( #[unstable(
feature = "fn_ptr_trait", feature = "fn_ptr_trait",
issue = "none", issue = "none",

View file

@ -474,6 +474,7 @@ macro_rules! nonzero_integer {
#[$stability:meta] #[$stability:meta]
Self = $Ty:ident, Self = $Ty:ident,
Primitive = $signedness:ident $Int:ident, Primitive = $signedness:ident $Int:ident,
SignedPrimitive = $Sint:ty,
UnsignedPrimitive = $Uint:ty, UnsignedPrimitive = $Uint:ty,
// Used in doc comments. // Used in doc comments.
@ -905,6 +906,7 @@ macro_rules! nonzero_integer {
nonzero_integer_signedness_dependent_methods! { nonzero_integer_signedness_dependent_methods! {
Primitive = $signedness $Int, Primitive = $signedness $Int,
SignedPrimitive = $Sint,
UnsignedPrimitive = $Uint, UnsignedPrimitive = $Uint,
} }
@ -1128,6 +1130,7 @@ macro_rules! nonzero_integer {
( (
Self = $Ty:ident, Self = $Ty:ident,
Primitive = unsigned $Int:ident, Primitive = unsigned $Int:ident,
SignedPrimitive = $Sint:ident,
rot = $rot:literal, rot = $rot:literal,
rot_op = $rot_op:literal, rot_op = $rot_op:literal,
rot_result = $rot_result:literal, rot_result = $rot_result:literal,
@ -1140,6 +1143,7 @@ macro_rules! nonzero_integer {
#[stable(feature = "nonzero", since = "1.28.0")] #[stable(feature = "nonzero", since = "1.28.0")]
Self = $Ty, Self = $Ty,
Primitive = unsigned $Int, Primitive = unsigned $Int,
SignedPrimitive = $Sint,
UnsignedPrimitive = $Int, UnsignedPrimitive = $Int,
rot = $rot, rot = $rot,
rot_op = $rot_op, rot_op = $rot_op,
@ -1154,7 +1158,7 @@ macro_rules! nonzero_integer {
( (
Self = $Ty:ident, Self = $Ty:ident,
Primitive = signed $Int:ident, Primitive = signed $Int:ident,
UnsignedPrimitive = $UInt:ident, UnsignedPrimitive = $Uint:ident,
rot = $rot:literal, rot = $rot:literal,
rot_op = $rot_op:literal, rot_op = $rot_op:literal,
rot_result = $rot_result:literal, rot_result = $rot_result:literal,
@ -1166,7 +1170,8 @@ macro_rules! nonzero_integer {
#[stable(feature = "signed_nonzero", since = "1.34.0")] #[stable(feature = "signed_nonzero", since = "1.34.0")]
Self = $Ty, Self = $Ty,
Primitive = signed $Int, Primitive = signed $Int,
UnsignedPrimitive = $UInt, SignedPrimitive = $Int,
UnsignedPrimitive = $Uint,
rot = $rot, rot = $rot,
rot_op = $rot_op, rot_op = $rot_op,
rot_result = $rot_result, rot_result = $rot_result,
@ -1286,6 +1291,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
// Associated items for unsigned nonzero types only. // Associated items for unsigned nonzero types only.
( (
Primitive = unsigned $Int:ident, Primitive = unsigned $Int:ident,
SignedPrimitive = $Sint:ty,
UnsignedPrimitive = $Uint:ty, UnsignedPrimitive = $Uint:ty,
) => { ) => {
/// The smallest value that can be represented by this non-zero /// The smallest value that can be represented by this non-zero
@ -1620,11 +1626,35 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
// results will be sqrt(1), which is 1, so a result can't be zero. // results will be sqrt(1), which is 1, so a result can't be zero.
unsafe { Self::new_unchecked(result) } unsafe { Self::new_unchecked(result) }
} }
/// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(integer_sign_cast)]
/// # use std::num::NonZero;
///
#[doc = concat!("let n = NonZero::<", stringify!($Int), ">::MAX;")]
///
#[doc = concat!("assert_eq!(n.cast_signed(), NonZero::new(-1", stringify!($Sint), ").unwrap());")]
/// ```
#[unstable(feature = "integer_sign_cast", issue = "125882")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
pub const fn cast_signed(self) -> NonZero<$Sint> {
// SAFETY: `self.get()` can't be zero
unsafe { NonZero::new_unchecked(self.get().cast_signed()) }
}
}; };
// Associated items for signed nonzero types only. // Associated items for signed nonzero types only.
( (
Primitive = signed $Int:ident, Primitive = signed $Int:ident,
SignedPrimitive = $Sint:ty,
UnsignedPrimitive = $Uint:ty, UnsignedPrimitive = $Uint:ty,
) => { ) => {
/// The smallest value that can be represented by this non-zero /// The smallest value that can be represented by this non-zero
@ -2035,12 +2065,37 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
// SAFETY: negation of nonzero cannot yield zero values. // SAFETY: negation of nonzero cannot yield zero values.
unsafe { Self::new_unchecked(result) } unsafe { Self::new_unchecked(result) }
} }
/// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(integer_sign_cast)]
/// # use std::num::NonZero;
///
#[doc = concat!("let n = NonZero::new(-1", stringify!($Int), ").unwrap();")]
///
#[doc = concat!("assert_eq!(n.cast_unsigned(), NonZero::<", stringify!($Uint), ">::MAX);")]
/// ```
#[unstable(feature = "integer_sign_cast", issue = "125882")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
pub const fn cast_unsigned(self) -> NonZero<$Uint> {
// SAFETY: `self.get()` can't be zero
unsafe { NonZero::new_unchecked(self.get().cast_unsigned()) }
}
}; };
} }
nonzero_integer! { nonzero_integer! {
Self = NonZeroU8, Self = NonZeroU8,
Primitive = unsigned u8, Primitive = unsigned u8,
SignedPrimitive = i8,
rot = 2, rot = 2,
rot_op = "0x82", rot_op = "0x82",
rot_result = "0xa", rot_result = "0xa",
@ -2052,6 +2107,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroU16, Self = NonZeroU16,
Primitive = unsigned u16, Primitive = unsigned u16,
SignedPrimitive = i16,
rot = 4, rot = 4,
rot_op = "0xa003", rot_op = "0xa003",
rot_result = "0x3a", rot_result = "0x3a",
@ -2063,6 +2119,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroU32, Self = NonZeroU32,
Primitive = unsigned u32, Primitive = unsigned u32,
SignedPrimitive = i32,
rot = 8, rot = 8,
rot_op = "0x10000b3", rot_op = "0x10000b3",
rot_result = "0xb301", rot_result = "0xb301",
@ -2074,6 +2131,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroU64, Self = NonZeroU64,
Primitive = unsigned u64, Primitive = unsigned u64,
SignedPrimitive = i64,
rot = 12, rot = 12,
rot_op = "0xaa00000000006e1", rot_op = "0xaa00000000006e1",
rot_result = "0x6e10aa", rot_result = "0x6e10aa",
@ -2085,6 +2143,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroU128, Self = NonZeroU128,
Primitive = unsigned u128, Primitive = unsigned u128,
SignedPrimitive = i128,
rot = 16, rot = 16,
rot_op = "0x13f40000000000000000000000004f76", rot_op = "0x13f40000000000000000000000004f76",
rot_result = "0x4f7613f4", rot_result = "0x4f7613f4",
@ -2097,6 +2156,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroUsize, Self = NonZeroUsize,
Primitive = unsigned usize, Primitive = unsigned usize,
SignedPrimitive = isize,
rot = 4, rot = 4,
rot_op = "0xa003", rot_op = "0xa003",
rot_result = "0x3a", rot_result = "0x3a",
@ -2109,6 +2169,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroUsize, Self = NonZeroUsize,
Primitive = unsigned usize, Primitive = unsigned usize,
SignedPrimitive = isize,
rot = 8, rot = 8,
rot_op = "0x10000b3", rot_op = "0x10000b3",
rot_result = "0xb301", rot_result = "0xb301",
@ -2121,6 +2182,7 @@ nonzero_integer! {
nonzero_integer! { nonzero_integer! {
Self = NonZeroUsize, Self = NonZeroUsize,
Primitive = unsigned usize, Primitive = unsigned usize,
SignedPrimitive = isize,
rot = 12, rot = 12,
rot_op = "0xaa00000000006e1", rot_op = "0xaa00000000006e1",
rot_result = "0x6e10aa", rot_result = "0x6e10aa",

View file

@ -740,29 +740,27 @@ impl Iterator for ReadDir {
// to `byte_offset` and thus does not require the full extent of `*entry_ptr` // to `byte_offset` and thus does not require the full extent of `*entry_ptr`
// to be in bounds of the same allocation, only the offset of the field // to be in bounds of the same allocation, only the offset of the field
// being referenced. // being referenced.
macro_rules! entry_field_ptr {
($field:ident) => {
&raw const (*entry_ptr).$field
};
}
// d_name is guaranteed to be null-terminated. // d_name is guaranteed to be null-terminated.
let name = CStr::from_ptr(entry_field_ptr!(d_name).cast()); let name = CStr::from_ptr((&raw const (*entry_ptr).d_name).cast());
let name_bytes = name.to_bytes(); let name_bytes = name.to_bytes();
if name_bytes == b"." || name_bytes == b".." { if name_bytes == b"." || name_bytes == b".." {
continue; continue;
} }
// When loading from a field, we can skip the `&raw const`; `(*entry_ptr).d_ino` as
// a value expression will do the right thing: `byte_offset` to the field and then
// only access those bytes.
#[cfg(not(target_os = "vita"))] #[cfg(not(target_os = "vita"))]
let entry = dirent64_min { let entry = dirent64_min {
d_ino: *entry_field_ptr!(d_ino) as u64, d_ino: (*entry_ptr).d_ino as u64,
#[cfg(not(any( #[cfg(not(any(
target_os = "solaris", target_os = "solaris",
target_os = "illumos", target_os = "illumos",
target_os = "aix", target_os = "aix",
target_os = "nto", target_os = "nto",
)))] )))]
d_type: *entry_field_ptr!(d_type) as u8, d_type: (*entry_ptr).d_type as u8,
}; };
#[cfg(target_os = "vita")] #[cfg(target_os = "vita")]

View file

@ -2,11 +2,11 @@
//@ aux-build:crateresolve1-2.rs //@ aux-build:crateresolve1-2.rs
//@ aux-build:crateresolve1-3.rs //@ aux-build:crateresolve1-3.rs
//@ normalize-stderr: "\.nll/" -> "/" //@ normalize-stderr: "crateresolve1\..+/auxiliary/" -> "crateresolve1/auxiliary/"
//@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "\\\?\\" -> ""
//@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" //@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib"
// NOTE: This test is duplicated at `tests/ui/error-codes/E0464.rs`. // NOTE: This test is duplicated at `tests/ui/error-codes/E0464.rs` and `E0523.rs`.
extern crate crateresolve1; extern crate crateresolve1;
//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found //~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found

View file

@ -4,7 +4,7 @@
//@ aux-build:crateresolve2-2.rs //@ aux-build:crateresolve2-2.rs
//@ aux-build:crateresolve2-3.rs //@ aux-build:crateresolve2-3.rs
//@ normalize-stderr: "\.nll/" -> "/" //@ normalize-stderr: "crateresolve2\..+/auxiliary/" -> "crateresolve2/auxiliary/"
//@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "\\\?\\" -> ""
extern crate crateresolve2; extern crate crateresolve2;

View file

@ -15,7 +15,7 @@ note: expected this to be `Foo`
LL | type Error = E; LL | type Error = E;
| ^ | ^
= note: required for the cast from `Box<Result<..., ()>>` to `Box<...>` = note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
= note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.ascii/E0271.long-type-hash.txt' = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console = note: consider using `--verbose` to print the full type name to the console
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,7 +1,7 @@
//@ revisions: ascii unicode //@ revisions: ascii unicode
//@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes //@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
//@ normalize-stderr: "long-type-\d+" -> "long-type-hash" //@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
trait Future { trait Future {
type Error; type Error;
} }

View file

@ -15,7 +15,7 @@ note: expected this to be `Foo`
LL │ type Error = E; LL │ type Error = E;
│ ━ │ ━
├ note: required for the cast from `Box<Result<..., ()>>` to `Box<...>` ├ note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.unicode/E0271.long-type-hash.txt' ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
╰ note: consider using `--verbose` to print the full type name to the console ╰ note: consider using `--verbose` to print the full type name to the console
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,6 +1,6 @@
//@ aux-build:found-staticlib.rs //@ aux-build:found-staticlib.rs
//@ normalize-stderr: "\.nll/" -> "/" //@ normalize-stderr: "E0462\..+/auxiliary/" -> "E0462/auxiliary/"
//@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "\\\?\\" -> ""
//@ normalize-stderr: "(lib)?found_staticlib\.[a-z]+" -> "libfound_staticlib.somelib" //@ normalize-stderr: "(lib)?found_staticlib\.[a-z]+" -> "libfound_staticlib.somelib"

View file

@ -2,7 +2,7 @@
//@ aux-build:crateresolve1-2.rs //@ aux-build:crateresolve1-2.rs
//@ aux-build:crateresolve1-3.rs //@ aux-build:crateresolve1-3.rs
//@ normalize-stderr: "\.nll/" -> "/" //@ normalize-stderr: "E0464\..+/auxiliary/" -> "E0464/auxiliary/"
//@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "\\\?\\" -> ""
//@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" //@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib"

View file

@ -2,7 +2,7 @@
//@ aux-build:crateresolve1-2.rs //@ aux-build:crateresolve1-2.rs
//@ aux-build:crateresolve1-3.rs //@ aux-build:crateresolve1-3.rs
//@ normalize-stderr: "\.nll/" -> "/" //@ normalize-stderr: "E0523\..+/auxiliary/" -> "E0523/auxiliary/"
//@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "\\\?\\" -> ""
//@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" //@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib"

View file

@ -1,5 +1,6 @@
//@ build-pass //@ build-pass
//@ ignore-pass (different metadata emitted in different modes) //@ ignore-pass (different metadata emitted in different modes)
//@ compile-flags: --json=diagnostic-short --json artifacts --error-format=json //@ compile-flags: --json=diagnostic-short --json artifacts --error-format=json
//@ normalize-stderr: "json-multiple\..+/libjson_multiple.rlib" -> "json-multiple/libjson_multiple.rlib"
#![crate_type = "lib"] #![crate_type = "lib"]

View file

@ -1,5 +1,6 @@
//@ build-pass //@ build-pass
//@ ignore-pass (different metadata emitted in different modes) //@ ignore-pass (different metadata emitted in different modes)
//@ compile-flags: --json=diagnostic-short,artifacts --error-format=json //@ compile-flags: --json=diagnostic-short,artifacts --error-format=json
//@ normalize-stderr: "json-options\..+/libjson_options.rlib" -> "json-options/libjson_options.rlib"
#![crate_type = "lib"] #![crate_type = "lib"]