diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 2ec509b91180e..e82b0f6d49673 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -273,7 +273,7 @@ cfg_if! { pub use std::cell::RefMut as MappedWriteGuard; pub use std::cell::RefMut as MappedLockGuard; - pub use std::cell::OnceCell; + pub use std::cell::OnceCell as OnceLock; use std::cell::RefCell as InnerRwLock; @@ -327,7 +327,7 @@ cfg_if! { pub use parking_lot::MappedMutexGuard as MappedLockGuard; - pub use std::sync::OnceLock as OnceCell; + pub use std::sync::OnceLock; pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c8b1ba5694e5d..9fcaf64317950 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -8,7 +8,7 @@ use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; +use rustc_data_structures::sync::{Lrc, OnceLock, WorkerLocal}; use rustc_errors::PResult; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; @@ -689,7 +689,7 @@ pub fn create_global_ctxt<'tcx>( lint_store: Lrc, dep_graph: DepGraph, untracked: Untracked, - gcx_cell: &'tcx OnceCell>, + gcx_cell: &'tcx OnceLock>, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, ) -> &'tcx GlobalCtxt<'tcx> { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index fc71c6c7e9aa6..2db7aa0e36710 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,7 +7,7 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceLock, RwLock, WorkerLocal}; use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::DepGraphFuture; @@ -78,7 +78,7 @@ impl Default for Query { pub struct Queries<'tcx> { compiler: &'tcx Compiler, - gcx_cell: OnceCell>, + gcx_cell: OnceLock>, arena: WorkerLocal>, hir_arena: WorkerLocal>, @@ -93,7 +93,7 @@ impl<'tcx> Queries<'tcx> { pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> { Queries { compiler, - gcx_cell: OnceCell::new(), + gcx_cell: OnceLock::new(), arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), parse: Default::default(), diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 4302b1618331d..f606fa483caf0 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -252,7 +252,10 @@ fn main() { } else if target.contains("windows-gnu") { println!("cargo:rustc-link-lib=shell32"); println!("cargo:rustc-link-lib=uuid"); - } else if target.contains("haiku") || target.contains("darwin") { + } else if target.contains("haiku") + || target.contains("darwin") + || (is_crossed && (target.contains("dragonfly") || target.contains("solaris"))) + { println!("cargo:rustc-link-lib=z"); } else if target.contains("netbsd") { println!("cargo:rustc-link-lib=z"); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 05e608c0d1a69..43c1d321f81f9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -9,7 +9,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceCell}; +use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceLock}; use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; @@ -93,7 +93,7 @@ pub(crate) struct CrateMetadata { /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. def_path_hash_map: DefPathHashMapRef<'static>, /// Likewise for ExpnHash. - expn_hash_map: OnceCell>, + expn_hash_map: OnceLock>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. alloc_decoding_state: AllocDecodingState, /// Caches decoded `DefKey`s. diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 0ad17e819c744..70d8f3bd54b80 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::OnceCell; +use rustc_data_structures::sync::OnceLock; use rustc_index::{IndexSlice, IndexVec}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use smallvec::SmallVec; @@ -23,11 +23,11 @@ pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option, - switch_sources: OnceCell, - is_cyclic: OnceCell, - reverse_postorder: OnceCell>, - dominators: OnceCell>, + predecessors: OnceLock, + switch_sources: OnceLock, + is_cyclic: OnceLock, + reverse_postorder: OnceLock>, + dominators: OnceLock>, } impl<'tcx> BasicBlocks<'tcx> { diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index a96230fdc94cc..d8aa377af4273 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -2,7 +2,7 @@ use crate::dep_graph::DepNodeIndex; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::{self, Sharded}; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::OnceLock; use rustc_index::{Idx, IndexVec}; use std::fmt::Debug; use std::hash::Hash; @@ -87,12 +87,12 @@ impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for SingleCacheSelector { } pub struct SingleCache { - cache: Lock>, + cache: OnceLock<(V, DepNodeIndex)>, } impl Default for SingleCache { fn default() -> Self { - SingleCache { cache: Lock::new(None) } + SingleCache { cache: OnceLock::new() } } } @@ -105,16 +105,16 @@ where #[inline(always)] fn lookup(&self, _key: &()) -> Option<(V, DepNodeIndex)> { - *self.cache.lock() + self.cache.get().copied() } #[inline] fn complete(&self, _key: (), value: V, index: DepNodeIndex) { - *self.cache.lock() = Some((value, index)); + self.cache.set((value, index)).ok(); } fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { - if let Some(value) = self.cache.lock().as_ref() { + if let Some(value) = self.cache.get() { f(&(), &value.0, value.1) } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fa04a59455518..486d60eab2101 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -313,7 +313,7 @@ enum LifetimeRibKind { /// Resolves elided lifetimes to `'static`, but gives a warning that this behavior /// is a bug and will be reverted soon. - AnonymousWarnToStatic(NodeId), + AnonymousWarn(NodeId), /// Signal we cannot find which should be the anonymous lifetime. ElisionFailure, @@ -1154,7 +1154,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } LifetimeRibKind::AnonymousCreateParameter { .. } | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::AnonymousWarnToStatic(_) + | LifetimeRibKind::AnonymousWarn(_) | LifetimeRibKind::Elided(_) | LifetimeRibKind::ElisionFailure | LifetimeRibKind::ConcreteAnonConst(_) @@ -1522,7 +1522,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // lifetime would be illegal. LifetimeRibKind::Item | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::AnonymousWarnToStatic(_) + | LifetimeRibKind::AnonymousWarn(_) | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many), // An anonymous lifetime is legal here, and bound to the right // place, go ahead. @@ -1585,7 +1585,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ElisionFailure | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::AnonymousWarnToStatic(_) => {} + | LifetimeRibKind::AnonymousWarn(_) => {} } } @@ -1625,8 +1625,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } - LifetimeRibKind::AnonymousWarnToStatic(node_id) => { - self.record_lifetime_res(lifetime.id, LifetimeRes::Static, elision_candidate); + LifetimeRibKind::AnonymousWarn(node_id) => { let msg = if elided { "`&` without an explicit lifetime name cannot be used here" } else { @@ -1642,7 +1641,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { span: lifetime.ident.span, }, ); - return; } LifetimeRibKind::AnonymousReportError => { let (msg, note) = if elided { @@ -1840,7 +1838,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // impl Foo for std::cell::Ref // note lack of '_ // async fn foo(_: std::cell::Ref) { ... } LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } - | LifetimeRibKind::AnonymousWarnToStatic(_) => { + | LifetimeRibKind::AnonymousWarn(_) => { let sess = self.r.tcx.sess; let mut err = rustc_errors::struct_span_err!( sess, @@ -2936,33 +2934,30 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { kind: LifetimeBinderKind::ConstItem, }, |this| { - this.with_lifetime_rib( - LifetimeRibKind::AnonymousWarnToStatic(item.id), - |this| { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - seen_trait_items, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); + this.with_lifetime_rib(LifetimeRibKind::AnonymousWarn(item.id), |this| { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); - this.visit_generics(generics); - this.visit_ty(ty); - if let Some(expr) = expr { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_body(expr, None); - } - }, - ); + this.visit_generics(generics); + this.visit_ty(ty); + if let Some(expr) = expr { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_body(expr, None); + } + }); }, ); } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 5334a75dc0649..d8e1f0877bfd9 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -5,7 +5,6 @@ use std::fmt::Debug; use std::ops::Index; -use std::string::ToString; use crate::rustc_internal; use crate::{ @@ -156,10 +155,23 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { } /// A type that provides internal information but that can still be used for debug purpose. -pub type Opaque = impl Debug + ToString + Clone; +#[derive(Clone)] +pub struct Opaque(String); + +impl std::fmt::Display for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::fmt::Debug for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } +} pub(crate) fn opaque(value: &T) -> Opaque { - format!("{value:?}") + Opaque(format!("{value:?}")) } pub struct StableMir { diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 1b8346281757d..2d43e62e97af3 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -20,6 +20,7 @@ use crate::rustc_smir::Tables; pub mod mir; pub mod ty; +pub mod visitor; /// Use String for now but we should replace it. pub type Symbol = String; diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/rustc_smir/src/stable_mir/visitor.rs new file mode 100644 index 0000000000000..c928eb1381f79 --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/visitor.rs @@ -0,0 +1,186 @@ +use std::ops::ControlFlow; + +use crate::rustc_internal::Opaque; + +use super::ty::{ + Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, + Promoted, RigidTy, TermKind, Ty, UnevaluatedConst, +}; + +pub trait Visitor: Sized { + type Break; + fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + ty.super_visit(self) + } + fn visit_const(&mut self, c: &Const) -> ControlFlow { + c.super_visit(self) + } +} + +pub trait Visitable { + fn visit(&self, visitor: &mut V) -> ControlFlow { + self.super_visit(visitor) + } + fn super_visit(&self, visitor: &mut V) -> ControlFlow; +} + +impl Visitable for Ty { + fn visit(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_ty(self) + } + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match self.kind() { + super::ty::TyKind::RigidTy(ty) => ty.visit(visitor), + super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor), + super::ty::TyKind::Param(_) => todo!(), + super::ty::TyKind::Bound(_, _) => todo!(), + } + } +} + +impl Visitable for Const { + fn visit(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_const(self) + } + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match &self.literal { + super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor), + super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor), + super::ty::ConstantKind::ParamCt(param) => param.visit(visitor), + } + } +} + +impl Visitable for Opaque { + fn super_visit(&self, _visitor: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl Visitable for Allocation { + fn super_visit(&self, _visitor: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl Visitable for UnevaluatedConst { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + let UnevaluatedConst { ty, def, args, promoted } = self; + ty.visit(visitor)?; + def.visit(visitor)?; + args.visit(visitor)?; + promoted.visit(visitor) + } +} + +impl Visitable for ConstDef { + fn super_visit(&self, _visitor: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl Visitable for Option { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match self { + Some(val) => val.visit(visitor), + None => ControlFlow::Continue(()), + } + } +} + +impl Visitable for Promoted { + fn super_visit(&self, _visitor: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl Visitable for GenericArgs { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + self.0.visit(visitor) + } +} + +impl Visitable for GenericArgKind { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match self { + GenericArgKind::Lifetime(lt) => lt.visit(visitor), + GenericArgKind::Type(t) => t.visit(visitor), + GenericArgKind::Const(c) => c.visit(visitor), + } + } +} + +impl Visitable for RigidTy { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match self { + RigidTy::Bool + | RigidTy::Char + | RigidTy::Int(_) + | RigidTy::Uint(_) + | RigidTy::Float(_) + | RigidTy::Never + | RigidTy::Foreign(_) + | RigidTy::Str => ControlFlow::Continue(()), + RigidTy::Array(t, c) => { + t.visit(visitor)?; + c.visit(visitor) + } + RigidTy::Slice(inner) => inner.visit(visitor), + RigidTy::RawPtr(ty, _) => ty.visit(visitor), + RigidTy::Ref(_, ty, _) => ty.visit(visitor), + RigidTy::FnDef(_, args) => args.visit(visitor), + RigidTy::FnPtr(sig) => sig.visit(visitor), + RigidTy::Closure(_, args) => args.visit(visitor), + RigidTy::Generator(_, args, _) => args.visit(visitor), + RigidTy::Dynamic(pred, r, _) => { + pred.visit(visitor)?; + r.visit(visitor) + } + RigidTy::Tuple(fields) => fields.visit(visitor), + RigidTy::Adt(_, args) => args.visit(visitor), + } + } +} + +impl Visitable for Vec { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + for arg in self { + arg.visit(visitor)?; + } + ControlFlow::Continue(()) + } +} + +impl Visitable for Binder { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + self.value.visit(visitor) + } +} + +impl Visitable for ExistentialPredicate { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match self { + ExistentialPredicate::Trait(tr) => tr.generic_args.visit(visitor), + ExistentialPredicate::Projection(p) => { + p.term.visit(visitor)?; + p.generic_args.visit(visitor) + } + ExistentialPredicate::AutoTrait(_) => ControlFlow::Continue(()), + } + } +} + +impl Visitable for TermKind { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match self { + TermKind::Type(t) => t.visit(visitor), + TermKind::Const(c) => c.visit(visitor), + } + } +} + +impl Visitable for FnSig { + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + self.inputs_and_output.visit(visitor) + } +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f39c41764403f..b97cb652076e4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -152,7 +152,6 @@ #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] #![feature(const_slice_index)] -#![feature(const_slice_is_ascii)] #![feature(const_slice_ptr_len)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5939dedbd1db0..7f8d673c179a3 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -41,6 +41,20 @@ macro_rules! nonzero_integers { /// with the exception that `0` is not a valid instance. #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] /// including in FFI. + /// + /// Thanks to the [null pointer optimization], + #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] + /// are guaranteed to have the same size and alignment: + /// + /// ``` + /// # use std::mem::{size_of, align_of}; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::>());")] + #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] + /// ``` + /// + /// [null pointer optimization]: crate::option#representation #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index becb6330997d8..f2909a81d4920 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -119,7 +119,7 @@ //! # Representation //! //! Rust guarantees to optimize the following types `T` such that -//! [`Option`] has the same size as `T`: +//! [`Option`] has the same size and alignment as `T`: //! //! * [`Box`] //! * `&U` diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index e0fd347a04950..6b3c4343ed361 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -43,9 +43,27 @@ use crate::slice::{self, SliceIndex}; /// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` /// is never used for mutation. /// +/// # Representation +/// +/// Thanks to the [null pointer optimization], +/// `NonNull` and `Option>` +/// are guaranteed to have the same size and alignment: +/// +/// ``` +/// # use std::mem::{size_of, align_of}; +/// use std::ptr::NonNull; +/// +/// assert_eq!(size_of::>(), size_of::>>()); +/// assert_eq!(align_of::>(), align_of::>>()); +/// +/// assert_eq!(size_of::>(), size_of::>>()); +/// assert_eq!(align_of::>(), align_of::>>()); +/// ``` +/// /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html /// [`PhantomData`]: crate::marker::PhantomData /// [`UnsafeCell`]: crate::cell::UnsafeCell +/// [null pointer optimization]: crate::option#representation #[stable(feature = "nonnull", since = "1.25.0")] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index f3311f76a7f06..5dc53caba0dd3 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -10,7 +10,7 @@ use crate::ops; impl [u8] { /// Checks if all bytes in this slice are within the ASCII range. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")] + #[rustc_const_stable(feature = "const_slice_is_ascii", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn is_ascii(&self) -> bool { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 23cebdb6c3b90..d5b0ab92c0947 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2322,7 +2322,7 @@ impl str { /// assert!(!non_ascii.is_ascii()); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")] + #[rustc_const_stable(feature = "const_slice_is_ascii", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn is_ascii(&self) -> bool { diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index ee9f6ed087c99..97e78d1778677 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -132,8 +132,8 @@ //! On all platforms, [`OsStr`] consists of a sequence of bytes that is encoded as a superset of //! UTF-8; see [`OsString`] for more details on its encoding on different platforms. //! -//! For limited, inexpensive conversions from and to bytes, see [`OsStr::as_os_str_bytes`] and -//! [`OsStr::from_os_str_bytes_unchecked`]. +//! For limited, inexpensive conversions from and to bytes, see [`OsStr::as_encoded_bytes`] and +//! [`OsStr::from_encoded_bytes_unchecked`]. //! //! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: https://www.unicode.org/glossary/#code_point diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 43cecb19b148e..93b9bf0cc209d 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -154,36 +154,34 @@ impl OsString { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_os_str_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// - /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_os_str_bytes`] can be + /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be /// split either immediately before or immediately after any valid non-empty UTF-8 substring. /// /// # Example /// /// ``` - /// #![feature(os_str_bytes)] - /// /// use std::ffi::OsStr; /// /// let os_str = OsStr::new("Mary had a little lamb"); - /// let bytes = os_str.as_os_str_bytes(); + /// let bytes = os_str.as_encoded_bytes(); /// let words = bytes.split(|b| *b == b' '); /// let words: Vec<&OsStr> = words.map(|word| { /// // SAFETY: - /// // - Each `word` only contains content that originated from `OsStr::as_os_str_bytes` + /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes` /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring - /// unsafe { OsStr::from_os_str_bytes_unchecked(word) } + /// unsafe { OsStr::from_encoded_bytes_unchecked(word) } /// }).collect(); /// ``` /// /// [conversions]: super#conversions #[inline] - #[unstable(feature = "os_str_bytes", issue = "111544")] - pub unsafe fn from_os_str_bytes_unchecked(bytes: Vec) -> Self { - OsString { inner: Buf::from_os_str_bytes_unchecked(bytes) } + #[stable(feature = "os_str_bytes", since = "CURRENT_RUSTC_VERSION")] + pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec) -> Self { + OsString { inner: Buf::from_encoded_bytes_unchecked(bytes) } } /// Converts to an [`OsStr`] slice. @@ -205,7 +203,7 @@ impl OsString { } /// Converts the `OsString` into a byte slice. To convert the byte slice back into an - /// `OsString`, use the [`OsStr::from_os_str_bytes_unchecked`] function. + /// `OsString`, use the [`OsStr::from_encoded_bytes_unchecked`] function. /// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit @@ -219,9 +217,9 @@ impl OsString { /// /// [`std::ffi`]: crate::ffi #[inline] - #[unstable(feature = "os_str_bytes", issue = "111544")] - pub fn into_os_str_bytes(self) -> Vec { - self.inner.into_os_str_bytes() + #[stable(feature = "os_str_bytes", since = "CURRENT_RUSTC_VERSION")] + pub fn into_encoded_bytes(self) -> Vec { + self.inner.into_encoded_bytes() } /// Converts the `OsString` into a [`String`] if it contains valid Unicode data. @@ -745,36 +743,34 @@ impl OsStr { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_os_str_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// - /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_os_str_bytes`] can be + /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be /// split either immediately before or immediately after any valid non-empty UTF-8 substring. /// /// # Example /// /// ``` - /// #![feature(os_str_bytes)] - /// /// use std::ffi::OsStr; /// /// let os_str = OsStr::new("Mary had a little lamb"); - /// let bytes = os_str.as_os_str_bytes(); + /// let bytes = os_str.as_encoded_bytes(); /// let words = bytes.split(|b| *b == b' '); /// let words: Vec<&OsStr> = words.map(|word| { /// // SAFETY: - /// // - Each `word` only contains content that originated from `OsStr::as_os_str_bytes` + /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes` /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring - /// unsafe { OsStr::from_os_str_bytes_unchecked(word) } + /// unsafe { OsStr::from_encoded_bytes_unchecked(word) } /// }).collect(); /// ``` /// /// [conversions]: super#conversions #[inline] - #[unstable(feature = "os_str_bytes", issue = "111544")] - pub unsafe fn from_os_str_bytes_unchecked(bytes: &[u8]) -> &Self { - Self::from_inner(Slice::from_os_str_bytes_unchecked(bytes)) + #[stable(feature = "os_str_bytes", since = "CURRENT_RUSTC_VERSION")] + pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self { + Self::from_inner(Slice::from_encoded_bytes_unchecked(bytes)) } #[inline] @@ -948,7 +944,7 @@ impl OsStr { } /// Converts an OS string slice to a byte slice. To convert the byte slice back into an OS - /// string slice, use the [`OsStr::from_os_str_bytes_unchecked`] function. + /// string slice, use the [`OsStr::from_encoded_bytes_unchecked`] function. /// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit @@ -962,9 +958,9 @@ impl OsStr { /// /// [`std::ffi`]: crate::ffi #[inline] - #[unstable(feature = "os_str_bytes", issue = "111544")] - pub fn as_os_str_bytes(&self) -> &[u8] { - self.inner.as_os_str_bytes() + #[stable(feature = "os_str_bytes", since = "CURRENT_RUSTC_VERSION")] + pub fn as_encoded_bytes(&self) -> &[u8] { + self.inner.as_encoded_bytes() } /// Converts this string to its ASCII lower case equivalent in-place. @@ -1270,7 +1266,7 @@ impl Default for &OsStr { impl PartialEq for OsStr { #[inline] fn eq(&self, other: &OsStr) -> bool { - self.as_os_str_bytes().eq(other.as_os_str_bytes()) + self.as_encoded_bytes().eq(other.as_encoded_bytes()) } } @@ -1297,23 +1293,23 @@ impl Eq for OsStr {} impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &OsStr) -> Option { - self.as_os_str_bytes().partial_cmp(other.as_os_str_bytes()) + self.as_encoded_bytes().partial_cmp(other.as_encoded_bytes()) } #[inline] fn lt(&self, other: &OsStr) -> bool { - self.as_os_str_bytes().lt(other.as_os_str_bytes()) + self.as_encoded_bytes().lt(other.as_encoded_bytes()) } #[inline] fn le(&self, other: &OsStr) -> bool { - self.as_os_str_bytes().le(other.as_os_str_bytes()) + self.as_encoded_bytes().le(other.as_encoded_bytes()) } #[inline] fn gt(&self, other: &OsStr) -> bool { - self.as_os_str_bytes().gt(other.as_os_str_bytes()) + self.as_encoded_bytes().gt(other.as_encoded_bytes()) } #[inline] fn ge(&self, other: &OsStr) -> bool { - self.as_os_str_bytes().ge(other.as_os_str_bytes()) + self.as_encoded_bytes().ge(other.as_encoded_bytes()) } } @@ -1332,7 +1328,7 @@ impl PartialOrd for OsStr { impl Ord for OsStr { #[inline] fn cmp(&self, other: &OsStr) -> cmp::Ordering { - self.as_os_str_bytes().cmp(other.as_os_str_bytes()) + self.as_encoded_bytes().cmp(other.as_encoded_bytes()) } } @@ -1382,7 +1378,7 @@ impl_cmp!(Cow<'a, OsStr>, OsString); impl Hash for OsStr { #[inline] fn hash(&self, state: &mut H) { - self.as_os_str_bytes().hash(state) + self.as_encoded_bytes().hash(state) } } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 5842c096f1ab7..60562f64c90d9 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -193,7 +193,7 @@ impl<'a> Prefix<'a> { fn len(&self) -> usize { use self::Prefix::*; fn os_str_len(s: &OsStr) -> usize { - s.as_os_str_bytes().len() + s.as_encoded_bytes().len() } match *self { Verbatim(x) => 4 + os_str_len(x), @@ -316,7 +316,7 @@ fn has_physical_root(s: &[u8], prefix: Option>) -> bool { // basic workhorse for splitting stem and extension fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { - if file.as_os_str_bytes() == b".." { + if file.as_encoded_bytes() == b".." { return (Some(file), None); } @@ -324,7 +324,7 @@ fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { // and back. This is safe to do because (1) we only look at ASCII // contents of the encoding and (2) new &OsStr values are produced // only from ASCII-bounded slices of existing &OsStr values. - let mut iter = file.as_os_str_bytes().rsplitn(2, |b| *b == b'.'); + let mut iter = file.as_encoded_bytes().rsplitn(2, |b| *b == b'.'); let after = iter.next(); let before = iter.next(); if before == Some(b"") { @@ -332,15 +332,15 @@ fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { } else { unsafe { ( - before.map(|s| OsStr::from_os_str_bytes_unchecked(s)), - after.map(|s| OsStr::from_os_str_bytes_unchecked(s)), + before.map(|s| OsStr::from_encoded_bytes_unchecked(s)), + after.map(|s| OsStr::from_encoded_bytes_unchecked(s)), ) } } } fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) { - let slice = file.as_os_str_bytes(); + let slice = file.as_encoded_bytes(); if slice == b".." { return (file, None); } @@ -357,8 +357,8 @@ fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) { let after = &slice[i + 1..]; unsafe { ( - OsStr::from_os_str_bytes_unchecked(before), - Some(OsStr::from_os_str_bytes_unchecked(after)), + OsStr::from_encoded_bytes_unchecked(before), + Some(OsStr::from_encoded_bytes_unchecked(after)), ) } } @@ -739,7 +739,7 @@ impl<'a> Components<'a> { // separately via `include_cur_dir` b".." => Some(Component::ParentDir), b"" => None, - _ => Some(Component::Normal(unsafe { OsStr::from_os_str_bytes_unchecked(comp) })), + _ => Some(Component::Normal(unsafe { OsStr::from_encoded_bytes_unchecked(comp) })), } } @@ -896,7 +896,7 @@ impl<'a> Iterator for Components<'a> { let raw = &self.path[..self.prefix_len()]; self.path = &self.path[self.prefix_len()..]; return Some(Component::Prefix(PrefixComponent { - raw: unsafe { OsStr::from_os_str_bytes_unchecked(raw) }, + raw: unsafe { OsStr::from_encoded_bytes_unchecked(raw) }, parsed: self.prefix.unwrap(), })); } @@ -968,7 +968,7 @@ impl<'a> DoubleEndedIterator for Components<'a> { State::Prefix if self.prefix_len() > 0 => { self.back = State::Done; return Some(Component::Prefix(PrefixComponent { - raw: unsafe { OsStr::from_os_str_bytes_unchecked(self.path) }, + raw: unsafe { OsStr::from_encoded_bytes_unchecked(self.path) }, parsed: self.prefix.unwrap(), })); } @@ -1477,17 +1477,17 @@ impl PathBuf { fn _set_extension(&mut self, extension: &OsStr) -> bool { let file_stem = match self.file_stem() { None => return false, - Some(f) => f.as_os_str_bytes(), + Some(f) => f.as_encoded_bytes(), }; // truncate until right after the file stem let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr(); - let start = self.inner.as_os_str_bytes().as_ptr().addr(); + let start = self.inner.as_encoded_bytes().as_ptr().addr(); let v = self.as_mut_vec(); v.truncate(end_file_stem.wrapping_sub(start)); // add the new extension, if any - let new = extension.as_os_str_bytes(); + let new = extension.as_encoded_bytes(); if !new.is_empty() { v.reserve_exact(new.len() + 1); v.push(b'.'); @@ -2007,11 +2007,11 @@ impl Path { // The following (private!) function allows construction of a path from a u8 // slice, which is only safe when it is known to follow the OsStr encoding. unsafe fn from_u8_slice(s: &[u8]) -> &Path { - unsafe { Path::new(OsStr::from_os_str_bytes_unchecked(s)) } + unsafe { Path::new(OsStr::from_encoded_bytes_unchecked(s)) } } // The following (private!) function reveals the byte encoding used for OsStr. fn as_u8_slice(&self) -> &[u8] { - self.inner.as_os_str_bytes() + self.inner.as_encoded_bytes() } /// Directly wraps a string slice as a `Path` slice. @@ -2609,7 +2609,7 @@ impl Path { fn _with_extension(&self, extension: &OsStr) -> PathBuf { let self_len = self.as_os_str().len(); - let self_bytes = self.as_os_str().as_os_str_bytes(); + let self_bytes = self.as_os_str().as_encoded_bytes(); let (new_capacity, slice_to_copy) = match self.extension() { None => { diff --git a/library/std/src/sys/common/small_c_string.rs b/library/std/src/sys/common/small_c_string.rs index 963d17a47e4c0..af9b18e372dab 100644 --- a/library/std/src/sys/common/small_c_string.rs +++ b/library/std/src/sys/common/small_c_string.rs @@ -19,7 +19,7 @@ pub fn run_path_with_cstr(path: &Path, f: F) -> io::Result where F: FnOnce(&CStr) -> io::Result, { - run_with_cstr(path.as_os_str().as_os_str_bytes(), f) + run_with_cstr(path.as_os_str().as_encoded_bytes(), f) } #[inline] diff --git a/library/std/src/sys/common/tests.rs b/library/std/src/sys/common/tests.rs index 0a1cbcbe8ef37..32dc18ee1cff9 100644 --- a/library/std/src/sys/common/tests.rs +++ b/library/std/src/sys/common/tests.rs @@ -8,7 +8,7 @@ use core::iter::repeat; fn stack_allocation_works() { let path = Path::new("abc"); let result = run_path_with_cstr(path, |p| { - assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap()); + assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap()); Ok(42) }); assert_eq!(result.unwrap(), 42); @@ -25,7 +25,7 @@ fn heap_allocation_works() { let path = repeat("a").take(384).collect::(); let path = Path::new(&path); let result = run_path_with_cstr(path, |p| { - assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap()); + assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap()); Ok(42) }); assert_eq!(result.unwrap(), 42); diff --git a/library/std/src/sys/solid/error.rs b/library/std/src/sys/solid/error.rs index d1877a8bcd2bf..547b4f3a9840e 100644 --- a/library/std/src/sys/solid/error.rs +++ b/library/std/src/sys/solid/error.rs @@ -31,11 +31,6 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> { } } -#[inline] -fn is_interrupted(er: abi::ER) -> bool { - false -} - pub fn decode_error_kind(er: abi::ER) -> ErrorKind { match er { // Success diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs index e7029174511ca..5af83653cf849 100644 --- a/library/std/src/sys/solid/mod.rs +++ b/library/std/src/sys/solid/mod.rs @@ -74,7 +74,7 @@ pub fn unsupported_err() -> crate::io::Error { #[inline] pub fn is_interrupted(code: i32) -> bool { - error::is_interrupted(code) + net::is_interrupted(code) } pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index bdd64ab02b770..6adced787f3bb 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -183,8 +183,7 @@ pub(super) fn error_name(er: abi::ER) -> Option<&'static str> { #[inline] pub fn is_interrupted(er: abi::ER) -> bool { - let errno = netc::SOLID_NET_ERR_BASE - er; - errno as libc::c_int == libc::EINTR + er == netc::SOLID_NET_ERR_BASE - libc::EINTR } pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs index 463b0a275157a..7bd2f656a24e5 100644 --- a/library/std/src/sys/unix/os_str.rs +++ b/library/std/src/sys/unix/os_str.rs @@ -97,12 +97,12 @@ impl AsInner<[u8]> for Buf { impl Buf { #[inline] - pub fn into_os_str_bytes(self) -> Vec { + pub fn into_encoded_bytes(self) -> Vec { self.inner } #[inline] - pub unsafe fn from_os_str_bytes_unchecked(s: Vec) -> Self { + pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self { Self { inner: s } } @@ -203,18 +203,18 @@ impl Buf { impl Slice { #[inline] - pub fn as_os_str_bytes(&self) -> &[u8] { + pub fn as_encoded_bytes(&self) -> &[u8] { &self.inner } #[inline] - pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice { + pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { unsafe { mem::transmute(s) } } #[inline] pub fn from_str(s: &str) -> &Slice { - unsafe { Slice::from_os_str_bytes_unchecked(s.as_bytes()) } + unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) } } pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { diff --git a/library/std/src/sys/unix/os_str/tests.rs b/library/std/src/sys/unix/os_str/tests.rs index 91bc0e61a4a5b..e2a99045e41f6 100644 --- a/library/std/src/sys/unix/os_str/tests.rs +++ b/library/std/src/sys/unix/os_str/tests.rs @@ -2,7 +2,7 @@ use super::*; #[test] fn slice_debug_output() { - let input = unsafe { Slice::from_os_str_bytes_unchecked(b"\xF0hello,\tworld") }; + let input = unsafe { Slice::from_encoded_bytes_unchecked(b"\xF0hello,\tworld") }; let expected = r#""\xF0hello,\tworld""#; let output = format!("{input:?}"); @@ -12,6 +12,6 @@ fn slice_debug_output() { #[test] fn display() { assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe { - Slice::from_os_str_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string() + Slice::from_encoded_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string() },); } diff --git a/library/std/src/sys/unix/path.rs b/library/std/src/sys/unix/path.rs index 935245f637b86..837f68d3eaff7 100644 --- a/library/std/src/sys/unix/path.rs +++ b/library/std/src/sys/unix/path.rs @@ -30,7 +30,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result { // Get the components, skipping the redundant leading "." component if it exists. let mut components = path.strip_prefix(".").unwrap_or(path).components(); - let path_os = path.as_os_str().as_os_str_bytes(); + let path_os = path.as_os_str().as_encoded_bytes(); let mut normalized = if path.is_absolute() { // "If a pathname begins with two successive characters, the diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 640648e870748..e7d1533f122df 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -164,9 +164,9 @@ pub enum ProgramKind { impl ProgramKind { fn new(program: &OsStr) -> Self { - if program.as_os_str_bytes().starts_with(b"/") { + if program.as_encoded_bytes().starts_with(b"/") { Self::Absolute - } else if program.as_os_str_bytes().contains(&b'/') { + } else if program.as_encoded_bytes().contains(&b'/') { // If the program has more than one component in it, it is a relative path. Self::Relative } else { diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs index 6b597f499bcdc..ee7dba6e5b362 100644 --- a/library/std/src/sys/windows/args.rs +++ b/library/std/src/sys/windows/args.rs @@ -226,7 +226,7 @@ pub(crate) fn append_arg(cmd: &mut Vec, arg: &Arg, force_quotes: bool) -> i // that it actually gets passed through on the command line or otherwise // it will be dropped entirely when parsed on the other end. ensure_no_nuls(arg)?; - let arg_bytes = arg.as_os_str_bytes(); + let arg_bytes = arg.as_encoded_bytes(); let (quote, escape) = match quote { Quote::Always => (true, true), Quote::Auto => { @@ -298,7 +298,7 @@ pub(crate) fn make_bat_command_line( const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>"; let force_quotes = match arg { Arg::Regular(arg) if !force_quotes => { - arg.as_os_str_bytes().iter().any(|c| SPECIAL.contains(c)) + arg.as_encoded_bytes().iter().any(|c| SPECIAL.contains(c)) } _ => force_quotes, }; diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs index 4708657a907f5..237854fac4e2a 100644 --- a/library/std/src/sys/windows/os_str.rs +++ b/library/std/src/sys/windows/os_str.rs @@ -64,12 +64,12 @@ impl fmt::Display for Slice { impl Buf { #[inline] - pub fn into_os_str_bytes(self) -> Vec { + pub fn into_encoded_bytes(self) -> Vec { self.inner.into_bytes() } #[inline] - pub unsafe fn from_os_str_bytes_unchecked(s: Vec) -> Self { + pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } } @@ -162,12 +162,12 @@ impl Buf { impl Slice { #[inline] - pub fn as_os_str_bytes(&self) -> &[u8] { + pub fn as_encoded_bytes(&self) -> &[u8] { self.inner.as_bytes() } #[inline] - pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice { + pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { mem::transmute(Wtf8::from_bytes_unchecked(s)) } diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index c9c2d10e6c444..8c0e07b35662f 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -22,12 +22,12 @@ pub fn is_verbatim_sep(b: u8) -> bool { /// Returns true if `path` looks like a lone filename. pub(crate) fn is_file_name(path: &OsStr) -> bool { - !path.as_os_str_bytes().iter().copied().any(is_sep_byte) + !path.as_encoded_bytes().iter().copied().any(is_sep_byte) } pub(crate) fn has_trailing_slash(path: &OsStr) -> bool { - let is_verbatim = path.as_os_str_bytes().starts_with(br"\\?\"); + let is_verbatim = path.as_encoded_bytes().starts_with(br"\\?\"); let is_separator = if is_verbatim { is_verbatim_sep } else { is_sep_byte }; - if let Some(&c) = path.as_os_str_bytes().last() { is_separator(c) } else { false } + if let Some(&c) = path.as_encoded_bytes().last() { is_separator(c) } else { false } } /// Appends a suffix to a path. @@ -49,7 +49,7 @@ impl<'a, const LEN: usize> PrefixParser<'a, LEN> { fn get_prefix(path: &OsStr) -> [u8; LEN] { let mut prefix = [0; LEN]; // SAFETY: Only ASCII characters are modified. - for (i, &ch) in path.as_os_str_bytes().iter().take(LEN).enumerate() { + for (i, &ch) in path.as_encoded_bytes().iter().take(LEN).enumerate() { prefix[i] = if ch == b'/' { b'\\' } else { ch }; } prefix @@ -82,7 +82,7 @@ impl<'a> PrefixParserSlice<'a, '_> { } fn prefix_bytes(&self) -> &'a [u8] { - &self.path.as_os_str_bytes()[..self.index] + &self.path.as_encoded_bytes()[..self.index] } fn finish(self) -> &'a OsStr { @@ -90,7 +90,7 @@ impl<'a> PrefixParserSlice<'a, '_> { // &[u8] and back. This is safe to do because (1) we only look at ASCII // contents of the encoding and (2) new &OsStr values are produced only // from ASCII-bounded slices of existing &OsStr values. - unsafe { OsStr::from_os_str_bytes_unchecked(&self.path.as_os_str_bytes()[self.index..]) } + unsafe { OsStr::from_encoded_bytes_unchecked(&self.path.as_encoded_bytes()[self.index..]) } } } @@ -162,7 +162,7 @@ fn parse_drive(path: &OsStr) -> Option { drive.is_ascii_alphabetic() } - match path.as_os_str_bytes() { + match path.as_encoded_bytes() { [drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()), _ => None, } @@ -171,7 +171,7 @@ fn parse_drive(path: &OsStr) -> Option { // Parses a drive prefix exactly, e.g. "C:" fn parse_drive_exact(path: &OsStr) -> Option { // only parse two bytes: the drive letter and the drive separator - if path.as_os_str_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) { + if path.as_encoded_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) { parse_drive(path) } else { None @@ -185,15 +185,15 @@ fn parse_drive_exact(path: &OsStr) -> Option { fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { let separator = if verbatim { is_verbatim_sep } else { is_sep_byte }; - match path.as_os_str_bytes().iter().position(|&x| separator(x)) { + match path.as_encoded_bytes().iter().position(|&x| separator(x)) { Some(separator_start) => { let separator_end = separator_start + 1; - let component = &path.as_os_str_bytes()[..separator_start]; + let component = &path.as_encoded_bytes()[..separator_start]; // Panic safe // The max `separator_end` is `bytes.len()` and `bytes[bytes.len()..]` is a valid index. - let path = &path.as_os_str_bytes()[separator_end..]; + let path = &path.as_encoded_bytes()[separator_end..]; // SAFETY: `path` is a valid wtf8 encoded slice and each of the separators ('/', '\') // is encoded in a single byte, therefore `bytes[separator_start]` and @@ -201,8 +201,8 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { // `bytes[..separator_start]` and `bytes[separator_end..]` are valid wtf8 slices. unsafe { ( - OsStr::from_os_str_bytes_unchecked(component), - OsStr::from_os_str_bytes_unchecked(path), + OsStr::from_encoded_bytes_unchecked(component), + OsStr::from_encoded_bytes_unchecked(path), ) } } @@ -323,7 +323,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result { // Verbatim paths should not be modified. if prefix.map(|x| x.is_verbatim()).unwrap_or(false) { // NULs in verbatim paths are rejected for consistency. - if path.as_os_str_bytes().contains(&0) { + if path.as_encoded_bytes().contains(&0) { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "strings passed to WinAPI cannot contain NULs", diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 92edd2f6112f3..6f46da1748a70 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -429,7 +429,7 @@ fn resolve_exe<'a>( // Test if the file name has the `exe` extension. // This does a case-insensitive `ends_with`. let has_exe_suffix = if exe_path.len() >= EXE_SUFFIX.len() { - exe_path.as_os_str_bytes()[exe_path.len() - EXE_SUFFIX.len()..] + exe_path.as_encoded_bytes()[exe_path.len() - EXE_SUFFIX.len()..] .eq_ignore_ascii_case(EXE_SUFFIX.as_bytes()) } else { false @@ -459,7 +459,7 @@ fn resolve_exe<'a>( // From the `CreateProcessW` docs: // > If the file name does not contain an extension, .exe is appended. // Note that this rule only applies when searching paths. - let has_extension = exe_path.as_os_str_bytes().contains(&b'.'); + let has_extension = exe_path.as_encoded_bytes().contains(&b'.'); // Search the directories given by `search_paths`. let result = search_paths(parent_paths, child_paths, |mut path| { diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 03dd9037808c6..816055cc4fe91 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,7 +8,6 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(round_ties_even)] -#![feature(os_str_bytes)] #![feature(lint_reasons)] #![feature(trait_upcasting)] // Configure clippy and other lints diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index f08f0aad5e764..a94b1ddcd95b9 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -24,7 +24,7 @@ pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> { } #[cfg(not(unix))] pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> { - // We cannot use `from_os_str_bytes_unchecked` here since we can't trust `bytes`. + // We cannot use `from_encoded_bytes_unchecked` here since we can't trust `bytes`. let s = std::str::from_utf8(bytes) .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?; Ok(OsStr::new(s)) @@ -83,7 +83,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ptr: Pointer>, size: u64, ) -> InterpResult<'tcx, (bool, u64)> { - let bytes = os_str.as_os_str_bytes(); + let bytes = os_str.as_encoded_bytes(); self.eval_context_mut().write_c_str(bytes, ptr, size) } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index beaef22075b40..dd2da3d22f286 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1344,7 +1344,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut name = dir_entry.file_name(); // not a Path as there are no separators! name.push("\0"); // Add a NUL terminator - let name_bytes = name.as_os_str_bytes(); + let name_bytes = name.as_encoded_bytes(); let name_len = u64::try_from(name_bytes.len()).unwrap(); let dirent64_layout = this.libc_ty_layout("dirent64"); @@ -1698,7 +1698,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Cow::Borrowed(resolved.as_ref()), crate::shims::os_str::PathConversion::HostToTarget, ); - let mut path_bytes = resolved.as_os_str_bytes(); + let mut path_bytes = resolved.as_encoded_bytes(); let bufsize: usize = bufsize.try_into().unwrap(); if path_bytes.len() > bufsize { path_bytes = &path_bytes[..bufsize] diff --git a/src/tools/miri/tests/utils/fs.rs b/src/tools/miri/tests/utils/fs.rs index 47904926b48b9..0242a2280689a 100644 --- a/src/tools/miri/tests/utils/fs.rs +++ b/src/tools/miri/tests/utils/fs.rs @@ -6,7 +6,7 @@ use super::miri_extern; pub fn host_to_target_path(path: OsString) -> PathBuf { use std::ffi::{CStr, CString}; - // Once into_os_str_bytes is stable we can use it here. + // Once into_encoded_bytes is stable we can use it here. // (Unstable features would need feature flags in each test...) let path = CString::new(path.into_string().unwrap()).unwrap(); let mut out = Vec::with_capacity(1024); diff --git a/tests/ui/associated-consts/double-elided.rs b/tests/ui/associated-consts/double-elided.rs new file mode 100644 index 0000000000000..fd0317781bb15 --- /dev/null +++ b/tests/ui/associated-consts/double-elided.rs @@ -0,0 +1,12 @@ +struct S; + +impl S { + const C: &&str = &""; + //~^ WARN `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| WARN `&` without an explicit lifetime name cannot be used here + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| ERROR in type `&&str`, reference has a longer lifetime than the data it references +} + +fn main() {} diff --git a/tests/ui/associated-consts/double-elided.stderr b/tests/ui/associated-consts/double-elided.stderr new file mode 100644 index 0000000000000..ba4e6a23e27e6 --- /dev/null +++ b/tests/ui/associated-consts/double-elided.stderr @@ -0,0 +1,47 @@ +warning: `&` without an explicit lifetime name cannot be used here + --> $DIR/double-elided.rs:4:14 + | +LL | const C: &&str = &""; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 + = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default +help: use the `'static` lifetime + | +LL | const C: &'static &str = &""; + | +++++++ + +warning: `&` without an explicit lifetime name cannot be used here + --> $DIR/double-elided.rs:4:15 + | +LL | const C: &&str = &""; + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 +help: use the `'static` lifetime + | +LL | const C: &&'static str = &""; + | +++++++ + +error[E0491]: in type `&&str`, reference has a longer lifetime than the data it references + --> $DIR/double-elided.rs:4:5 + | +LL | const C: &&str = &""; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the anonymous lifetime as defined here + --> $DIR/double-elided.rs:4:14 + | +LL | const C: &&str = &""; + | ^ +note: but the referenced data is only valid for the anonymous lifetime as defined here + --> $DIR/double-elided.rs:4:14 + | +LL | const C: &&str = &""; + | ^ + +error: aborting due to previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0491`. diff --git a/triagebot.toml b/triagebot.toml index 6f7efd4c3db4e..6847e8a00be54 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -585,7 +585,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "clubby789"] +users_on_vacation = ["jyn514", "clubby789", "spastorino"] [assign.adhoc_groups] compiler-team = [