diff --git a/Cargo.lock b/Cargo.lock index 3ebc0ee928589..39049cd7e2c6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3626,6 +3626,7 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ + "bitflags", "rustc_abi", "rustc_ast", "rustc_attr_ir", diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 0fc1f96dfe469..f2c6ffe44cdfd 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -11,13 +11,13 @@ #![allow(clippy::mut_from_ref)] // Arena allocators are one place where this pattern is fine. #![allow(internal_features)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(test(no_crate_inject, attr(deny(warnings))))] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(rustc_attrs)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end use std::alloc::Layout; diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 9dc5f81581e87..350687ba299c7 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +bitflags = "2.4.1" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_ir = { path = "../rustc_attr_ir" } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e30fdfcebfdb8..4b6e897da4c87 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,7 +56,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; -use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; +use rustc_hir::def::{CtorKind, DefKind, Namespace, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; @@ -1420,10 +1420,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let ct = self.arena.alloc(ct); return GenericArg::Const(ct.try_as_ambig_ct().unwrap()); } - TyKind::GcaMacro(expr) if self.tcx.features().gca_min_const_items() => { + TyKind::GcaMacro(expr) if self.tcx.features().gca() => { let ct = match self.can_lower_expr_to_const_arg_direct( expr, - DirectConstArgContext::MacrolessMinGenericConstArgs, + self.direct_const_arg_context_enabled_by_gca_macro(), ) { Ok(()) => self.lower_expr_to_const_arg_direct(expr, None), Err(e) => e.emit(self), @@ -2628,18 +2628,12 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, ) -> hir::ConstItemRhs<'hir> { let is_direct = |body| { - if self.tcx.features().gca_macroless_items() { - self.can_lower_expr_to_const_arg_direct( - body, - DirectConstArgContext::MacrolessMinGenericConstArgs, - ) - .is_ok() + let context = if self.tcx.features().gca_macroless_items() { + self.direct_const_arg_context_enabled_by_gca_macro() } else { - // do not check can_lower_expr_to_const_arg_direct, but rather just - // ExprKind::GcaMacro, because we don't want e.g. - // `impl { const C: u8 = N; }` to be a direct-rhs const - matches!(body, Expr { kind: ExprKind::GcaMacro(_), .. }) - } + DirectConstArgContext::GCA_MACRO + }; + self.can_lower_expr_to_const_arg_direct(body, context).is_ok() }; if self.tcx.features().gca_min_const_items() && let Some(body) = body @@ -2653,13 +2647,25 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn direct_const_arg_context_enabled_by_gca_macro(&self) -> DirectConstArgContext { + let mut result = DirectConstArgContext::GCA_BASE_FEATURES; + if self.tcx.features().gca_min_const_items() { + result |= DirectConstArgContext::GCA_MIN_CONST_ITEMS; + } + if self.tcx.features().gca_adts() { + result |= DirectConstArgContext::GCA_ADTS; + } + result + } + + /// Only valid for const *arg* contexts, not const *item* contexts. fn ambient_direct_const_arg_context(&self) -> DirectConstArgContext { if self.tcx.features().gca_macroless_args() { - DirectConstArgContext::MacrolessMinGenericConstArgs - } else if self.tcx.features().gca_min_const_items() { - DirectConstArgContext::MinGenericConstArgs + self.direct_const_arg_context_enabled_by_gca_macro() + } else if self.tcx.features().gca() { + DirectConstArgContext::GCA } else { - DirectConstArgContext::Stable + DirectConstArgContext::STABLE } } @@ -2671,9 +2677,16 @@ impl<'hir> LoweringContext<'_, 'hir> { res: Option>, context: DirectConstArgContext, ) -> Result<(), UnrepresentableConstArgError> { - if let DirectConstArgContext::MacrolessMinGenericConstArgs = context { + if context.contains(DirectConstArgContext::PATH_ANY) { + Ok(()) + } else if context.contains(DirectConstArgContext::PATH_CONST_CTOR) + && matches!(res, Some(Res::Def(DefKind::Ctor(_, CtorKind::Const), _))) + { + // FIXME(gca_adts): This check is incomplete. Type-relative paths and other complicating + // factors make things very difficult - e.g. `>::None` Ok(()) - } else if qself.is_none() + } else if context.contains(DirectConstArgContext::PATH_PLAIN_PARAM) + && qself.is_none() && path.is_single_argless_ident() && matches!(res, Some(Res::Def(DefKind::ConstParam, _))) { @@ -2689,59 +2702,61 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &Expr, context: DirectConstArgContext, ) -> Result<(), UnrepresentableConstArgError> { - use DirectConstArgContext::*; // Note the only stable case is currently ExprKind::Path - match (&expr.kind, context) { - ( - ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args), - MacrolessMinGenericConstArgs, - ) => { + match &expr.kind { + ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args) + if context.contains(DirectConstArgContext::TUPLE_CALL) => + { for arg in args { self.can_lower_expr_to_const_arg_direct(arg, context)?; } Ok(()) } - (ExprKind::Tup(exprs), MacrolessMinGenericConstArgs) => { + ExprKind::Tup(exprs) if context.contains(DirectConstArgContext::TUPLE) => { for expr in exprs { self.can_lower_expr_to_const_arg_direct(expr, context)?; } Ok(()) } - (ExprKind::Path(qself, path), _) => { + ExprKind::Path(qself, path) => { let res = self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); self.can_lower_path_to_const_arg_direct(qself, path, expr.span, res, context) } - (ExprKind::Struct(se), MacrolessMinGenericConstArgs) => { + ExprKind::Struct(se) if context.contains(DirectConstArgContext::STRUCT) => { for f in &se.fields { self.can_lower_expr_to_const_arg_direct(&f.expr, context)?; } Ok(()) } - (ExprKind::Array(elements), MacrolessMinGenericConstArgs) => { + ExprKind::Array(elements) if context.contains(DirectConstArgContext::ARRAY) => { for element in elements { self.can_lower_expr_to_const_arg_direct(element, context)?; } Ok(()) } - (ExprKind::Underscore, MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::Paren(expr), MacrolessMinGenericConstArgs) => { + ExprKind::Underscore if context.contains(DirectConstArgContext::UNDERSCORE) => Ok(()), + ExprKind::Paren(expr) if context.contains(DirectConstArgContext::PAREN) => { self.can_lower_expr_to_const_arg_direct(expr, context) } - (ExprKind::Block(block, _), MacrolessMinGenericConstArgs) - if let [stmt] = block.stmts.as_slice() + ExprKind::Block(block, _) + if context.contains(DirectConstArgContext::BLOCK) + && let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind => { self.can_lower_expr_to_const_arg_direct(expr, context) } - (ExprKind::Lit(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::Unary(UnOp::Neg, inner_expr), MacrolessMinGenericConstArgs) - if let ExprKind::Lit(_) = &inner_expr.kind => + ExprKind::Lit(_) if context.contains(DirectConstArgContext::LIT) => Ok(()), + ExprKind::Unary(UnOp::Neg, inner_expr) + if context.contains(DirectConstArgContext::LIT) + && let ExprKind::Lit(_) = &inner_expr.kind => { Ok(()) } - (ExprKind::ConstBlock(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::GcaMacro(_), MacrolessMinGenericConstArgs | MinGenericConstArgs) => { + ExprKind::ConstBlock(_) if context.contains(DirectConstArgContext::CONST_BLOCK) => { + Ok(()) + } + ExprKind::GcaMacro(_) if context.contains(DirectConstArgContext::GCA_MACRO) => { // Always report this as able to be represented directly. If it turns out not to be, // `lower_expr_to_const_arg_direct` will report an error. Ok(()) @@ -2927,11 +2942,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // `can_lower_expr_to_const_arg_direct` always returns success upon encountering a // ExprKind::GcaMacro, which effectively forces the expression to be lowered as a // direct arg. If it actually turns out to not be possible, emit an error instead. - // Always use MacrolessMinGenericConstArgs, even if we're under regular GCA, because - // that's what the macro means: to enter a context that is like macroless GCA. match self.can_lower_expr_to_const_arg_direct( expr, - DirectConstArgContext::MacrolessMinGenericConstArgs, + self.direct_const_arg_context_enabled_by_gca_macro(), ) { Ok(()) => self.lower_expr_to_const_arg_direct(expr, id_override), Err(err) => err.emit(self), @@ -3273,19 +3286,53 @@ impl<'hir> GenericArgsCtor<'hir> { } } -#[derive(Copy, Clone, Debug)] -enum DirectConstArgContext { +bitflags::bitflags! { + #[derive(Copy, Clone, Debug)] + struct DirectConstArgContext: u16 { + const TUPLE_CALL = 1 << 0; + const TUPLE = 1 << 1; + const PATH_PLAIN_PARAM = 1 << 2; + const PATH_CONST_CTOR = 1 << 3; + const PATH_ANY = 1 << 4; + const STRUCT = 1 << 5; + const ARRAY = 1 << 6; + const UNDERSCORE = 1 << 7; + const PAREN = 1 << 8; + const BLOCK = 1 << 9; + const LIT = 1 << 10; + const CONST_BLOCK = 1 << 11; + const GCA_MACRO = 1 << 12; + } +} + +impl DirectConstArgContext { /// The only allowed direct const arg representation is simple paths that nameres to generic /// const parameters. - Stable, + const STABLE: DirectConstArgContext = Self::PATH_PLAIN_PARAM; + /// The allowed representations are what is allowed on stable, plus the `gca!` macro. - MinGenericConstArgs, - /// Expressions attempt to be lowered directly, and if that fails, the expression falls back to - /// being represented as an anon const. + const GCA: DirectConstArgContext = Self::STABLE.union(Self::GCA_MACRO); + + /// These expressions are allowed inside the `gca!` macro, regardless of what feature is + /// enabling the base `gca!` functionality. /// - /// This context is also used under MinGenericConstArgs inside a `gca!` macro, for - /// simplicity, as they allow the same code. - MacrolessMinGenericConstArgs, + /// These are also allowed under macroless features without a `gca!` macro. + const GCA_BASE_FEATURES: DirectConstArgContext = Self::GCA + .union(DirectConstArgContext::UNDERSCORE) + .union(DirectConstArgContext::PAREN) + .union(DirectConstArgContext::BLOCK) + .union(DirectConstArgContext::LIT) + .union(DirectConstArgContext::CONST_BLOCK); + + /// These are allowed under `#![feature(gca_min_const_items)]` + const GCA_MIN_CONST_ITEMS: DirectConstArgContext = DirectConstArgContext::PATH_ANY; + + /// These are allowed under `#![feature(gca_adts)]` + const GCA_ADTS: DirectConstArgContext = DirectConstArgContext::PATH_CONST_CTOR + .union(DirectConstArgContext::TUPLE_CALL) + .union(DirectConstArgContext::TUPLE) + .union(DirectConstArgContext::STRUCT) + .union(DirectConstArgContext::ARRAY); } #[derive(Debug)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0232e83de841d..45fa1863e715f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -3,7 +3,7 @@ use rustc_ast::{self as ast, AttrVec, GenericBound, NodeId, PatKind, attr, token use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_attr_parsing::AttributeParser; use rustc_errors::msg; -use rustc_feature::Features; +use rustc_feature::{DependentFeature, Features}; use rustc_session::Session; use rustc_session::diagnostics::{feature_err, feature_warn}; use rustc_span::{Span, Spanned, sym}; @@ -652,26 +652,47 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } fn check_dependent_features(sess: &Session, features: &Features) { - for &(parent, children) in - rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent)) + for &(parent, ref children) in + rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, children)| { + features.enabled(*parent) && !check_enabled(features, children) + }) { - if children.iter().any(|f| !features.enabled(*f)) { - let parent_span = features - .enabled_features_iter_stable_order() - .find_map(|(name, span)| (name == parent).then_some(span)) - .unwrap(); - // FIXME: should probably format this in fluent instead of here - let missing = children + let parent_span = features + .enabled_features_iter_stable_order() + .find_map(|(name, span)| (name == parent).then_some(span)) + .unwrap(); + // FIXME: should probably format this in fluent instead of here + let missing = format(features, &children); + sess.dcx().emit_err(diagnostics::MissingDependentFeatures { parent_span, parent, missing }); + } + + fn check_enabled(features: &Features, feature: &DependentFeature) -> bool { + match feature { + DependentFeature::And(children) => { + children.iter().all(|child| check_enabled(features, child)) + } + DependentFeature::Or(children) => { + children.iter().any(|child| check_enabled(features, child)) + } + DependentFeature::Leaf(symbol) => features.enabled(*symbol), + } + } + + fn format(features: &Features, feature: &DependentFeature) -> String { + // FIXME: parentheses/precedence + match feature { + DependentFeature::And(children) => children .iter() - .filter(|f| !features.enabled(**f)) - .map(|s| format!("`{}`", s.as_str())) - .intersperse(String::from(", ")) - .collect(); - sess.dcx().emit_err(diagnostics::MissingDependentFeatures { - parent_span, - parent, - missing, - }); + .filter(|child| !check_enabled(features, child)) + .map(|child| format(features, child)) + .intersperse(String::from(" and ")) + .collect(), + DependentFeature::Or(children) => children + .iter() + .map(|child| format(features, child)) + .intersperse(String::from(" or ")) + .collect(), + DependentFeature::Leaf(symbol) => format!("`{}`", symbol.as_str()), } } } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 041763f57fc9e..4ebd6ef9f92b3 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -12,6 +12,7 @@ #![allow(rustc::potential_query_instability)] #![cfg_attr(bootstrap, feature(allocator_api))] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(not(bootstrap), feature(allocator_ext))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] @@ -35,7 +36,6 @@ #![feature(thread_id_value)] #![feature(trusted_len)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // This allows derive macros to reference this crate diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 210f04a115831..22076a95cea09 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -191,8 +191,16 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) HandledOptions::HelpOnly(matches) => (matches, true), }; - let sopts = config::build_session_options(&mut default_early_dcx, &matches); - // fully initialize ice path static once unstable options are available as context + // For the purposes of checking that an --edition was passed, we ignore `-`. + let warn_unspecified_edition = match &matches.free[..] { + [] => false, + // We explicitly don't emit the note if we're consuming code from stdin. This can happen + // on some cargo invocations too. + [name] if name == "-" => false, + _ => true, + }; + let sopts = + config::build_session_options(&mut default_early_dcx, &matches, warn_unspecified_edition); let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); if let Some(ref code) = matches.opt_str("explain") { diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 5b9b899fc463f..83bf4f47a8ac9 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -133,6 +133,6 @@ pub use builtin_attrs::{ }; pub use removed::REMOVED_LANG_FEATURES; pub use unstable::{ - DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, - TRACK_FEATURE, UNSTABLE_LANG_FEATURES, + DEPENDENT_FEATURES, DependentFeature, EnabledLangFeature, EnabledLibFeature, Features, + INCOMPATIBLE_FEATURES, TRACK_FEATURE, UNSTABLE_LANG_FEATURES, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 35c0a28a18f8f..cb6a1d39b1dd8 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -119,6 +119,13 @@ impl Features { false } } + + /// The generic_const_args family of features has a set of common behavior that can be enabled + /// by either `gca_min_const_items` or `gca_adts`. There is no actual `gca` base feature, but + /// this method acts as one. + pub fn gca(&self) -> bool { + self.gca_min_const_items() || self.gca_adts() + } } macro_rules! declare_features { @@ -548,6 +555,8 @@ declare_features! ( (internal, freeze_impls, "1.78.0", Some(121675)), /// Frontmatter `---` blocks for use by external tools. (unstable, frontmatter, "1.88.0", Some(136889)), + /// Allows using ADTs in directly represented generic const args. + (incomplete, gca_adts, "CURRENT_RUSTC_VERSION", Some(163420)), /// Allows using generics in more complex const expressions, based on definitional equality. (incomplete, gca_const_items, "1.95.0", Some(151972)), /// Allows directly represented gca_const_items without the `gca!` macro. @@ -859,10 +868,25 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural), ]; +pub enum DependentFeature { + And(&'static [DependentFeature]), + Or(&'static [DependentFeature]), + Leaf(Symbol), +} + /// Some features require one or more other features to be enabled. -pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ - (sym::gca_const_items, &[sym::gca_min_const_items]), - (sym::gca_macroless_args, &[sym::gca_min_const_items]), - (sym::gca_macroless_items, &[sym::gca_min_const_items]), - (sym::unsized_const_params, &[sym::adt_const_params]), +pub const DEPENDENT_FEATURES: &[(Symbol, DependentFeature)] = &[ + // tidy-alphabetical-start + ( + sym::gca_adts, + DependentFeature::Or(&[ + DependentFeature::Leaf(sym::min_adt_const_params), + DependentFeature::Leaf(sym::adt_const_params), + ]), + ), + (sym::gca_const_items, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::gca_macroless_args, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::gca_macroless_items, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::unsized_const_params, DependentFeature::Leaf(sym::adt_const_params)), + // tidy-alphabetical-end ]; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2c626ab7dc9f3..1cd1fc356ca7d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1803,7 +1803,7 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin debug_assert_matches!(const_arg.kind, hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) if *def_id == def); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().gca_min_const_items() { + } else if tcx.features().gca() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Repeat(_, repeat_count), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9605c777e55a9..4d43a9ca5700e 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -224,7 +224,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Node::AnonConst, or whether it will be represented directly, so it must generate a // DefId. If it ends up being direct, this DefId is then attached to the top-level // ConstArg, which is what we are seeing here. - debug_assert!(tcx.features().gca_min_const_items()); + debug_assert!(tcx.features().gca()); // Forward to the real parent. Some(tcx.local_parent(def_id)) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 7dba6b6b5f630..ba715633d30d7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -370,7 +370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && let Some(hir_ty) = constraint.ty() && let ty = self.lower_ty(hir_ty) && (ty.is_enum() || ty.references_error()) - && tcx.features().gca_min_const_items() + && tcx.features().gca() { Some(diagnostics::AssocKindMismatchWrapInBracesSugg { lo: hir_ty.span.shrink_to_lo(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index fe9a496f1200f..4fa02926f15d8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3120,7 +3120,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) } - /// `def_id` is a const item used in the type system. Checks if that's OK. + /// `alias_const` is a const item used in the type system. Checks if that's OK. fn check_const_item_in_type_system( &self, alias_const: ty::AliasConstKind<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index dbbf068185c23..c0abcc3a6119a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -57,12 +57,12 @@ This API is completely unstable and subject to change. // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(default_field_values)] #![feature(gen_blocks)] #![feature(iter_intersperse)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // These are used by Clippy. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 178585984cf27..aee246a61fb1e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -524,8 +524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, MethodCallOnDivergingInferenceVariable, ); - let root_ty = Ty::new_var(self.tcx, ty_id); - self.demand_eqtype(span, root_ty, self.tcx.types.never); + self.demand_eqtype(span, ty, self.tcx.types.never); } else { let guar = match *ty.kind() { _ if let Some(guar) = self.tainted_by_errors() => guar, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0d584be4ad0b0..3f59afa31de84 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -42,7 +42,7 @@ where { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(args).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, true); let target = rustc_session::config::build_target_config( &early_dcx, &sessopts.target_triple, @@ -941,7 +941,7 @@ fn test_edition_parsing() { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, false); assert!(sessopts.edition == Edition::Edition2018) } @@ -952,7 +952,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { // `-Zassumptions-on-binders` alone enables the next solver globally. let matches = optgroups().parse(&["-Zassumptions-on-binders".to_string()]).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); @@ -963,7 +963,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { ["-Znext-solver=coherence".to_string(), "-Zassumptions-on-binders".to_string()], ] { let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); } @@ -976,7 +976,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { ["-Znext-solver=no".to_string(), "-Zassumptions-on-binders".to_string()], ] { let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index aea843ac0384c..10693448ea685 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -15,7 +15,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::UnordMap; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId}; -use rustc_hir::definitions::Definitions; +use rustc_hir::definitions::{DefPathData, Definitions}; use rustc_index::IndexVec; use rustc_lint_defs as lint; use rustc_lint_defs::builtin::UNUSED_CRATE_DEPENDENCIES; @@ -1358,14 +1358,24 @@ impl CStore { let cnum = self.resolve_crate(tcx, name, item.span, dep_kind, CrateOrigin::Extern)?; - let path_len = definitions.def_path(def_id).data.len(); + let def_path = definitions.def_path(def_id); + // An extern crate is only globally nameable if every segment in its path + // is in the type namespace (i.e., it is purely nested inside modules). + // If any segment is in the value namespace (e.g. inside a fn or const), + // it is unnameable from outside that block. + let is_unnameable = + def_path.data.iter().any(|d| !matches!(d.data, DefPathData::TypeNs(_))); self.update_extern_crate( cnum, name, ExternCrate { - src: ExternCrateSource::Extern(def_id.to_def_id()), + src: if is_unnameable { + ExternCrateSource::Path + } else { + ExternCrateSource::Extern(def_id.to_def_id()) + }, span: item.span, - path_len, + path_len: if is_unnameable { usize::MAX } else { def_path.data.len() }, dependency_of: LOCAL_CRATE, }, ); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 27b36c23daf46..7dd920c7e39bd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -189,7 +189,7 @@ pub(super) trait LazyDecoder: BlobDecoder { self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len)) } - fn read_lazy_table(&mut self, width: usize, len: usize) -> LazyTable { + fn read_lazy_table(&mut self, width: usize, len: usize) -> LazyTable { self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len)) } @@ -667,7 +667,7 @@ impl Decodable for LazyArray { } } -impl Decodable for LazyTable { +impl Decodable for LazyTable { fn decode(decoder: &mut D) -> Self { let width = decoder.read_usize(); let len = decoder.read_usize(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index afa5646bea80e..40b61a52d2310 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx, T> Encodable> for LazyArray { } } -impl<'a, 'tcx, I, T> Encodable> for LazyTable { +impl<'a, 'tcx, Ie, Id, T> Encodable> for LazyTable { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) { e.emit_usize(self.width); e.emit_usize(self.len); @@ -547,7 +547,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } - fn encode_source_map(&mut self) -> LazyTable>> { + fn encode_source_map( + &mut self, + ) -> LazyTable>> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -2004,9 +2006,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) { - let mut syntax_contexts: TableBuilder<_, _> = Default::default(); - let mut expn_data_table: TableBuilder<_, _> = Default::default(); - let mut expn_hash_table: TableBuilder<_, _> = Default::default(); + let mut syntax_contexts: TableBuilder<_, _, _> = Default::default(); + let mut expn_data_table: TableBuilder<_, _, _> = Default::default(); + let mut expn_hash_table: TableBuilder<_, _, _> = Default::default(); HygieneEncodeContext::encode( &Rc::clone(&self.hygiene_ctxt), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e3f3257acc137..b70151604f679 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -48,6 +48,7 @@ use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; use crate::eii::EiiMapEncodedKeyValue; +use crate::rmeta::table::TableBuilderSingleIdx; mod decoder; mod def_path_hash_map; @@ -143,22 +144,27 @@ impl LazyArray { /// Random-access table (i.e. offering constant-time `get`/`set`), similar to /// `LazyArray`, but without requiring encoding or decoding all the values /// eagerly and in-order. -struct LazyTable { +/// +/// `IdxEncode` - is a type of index that is used to write to the table, +/// `IdxDecode` - is a type of index that is used to read from the table. +struct LazyTable { position: NonZero, /// The encoded size of the elements of a table is selected at runtime to drop /// trailing zeroes. This is the number of bytes used for each table element. width: usize, /// How many elements are in the table. len: usize, - _marker: PhantomData T>, + _marker: PhantomData T>, } -impl LazyTable { +type LazyTableSingleIdx = LazyTable; + +impl LazyTable { fn from_position_and_encoded_size( position: NonZero, width: usize, len: usize, - ) -> LazyTable { + ) -> LazyTable { LazyTable { position, width, len, _marker: PhantomData } } } @@ -177,8 +183,8 @@ impl Clone for LazyArray { } } -impl Copy for LazyTable {} -impl Clone for LazyTable { +impl Copy for LazyTable {} +impl Clone for LazyTable { fn clone(&self) -> Self { *self } @@ -199,9 +205,9 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; -type ExpnDataTable = LazyTable>>; -type ExpnHashTable = LazyTable>>; +type SyntaxContextTable = LazyTableSingleIdx>>; +type ExpnDataTable = LazyTableSingleIdx>>; +type ExpnHashTable = LazyTableSingleIdx>>; #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct ProcMacroData { @@ -305,7 +311,7 @@ pub(crate) struct CrateRoot { def_path_hash_map: LazyValue>, - source_map: LazyTable>>, + source_map: LazyTableSingleIdx>>, target_modifiers: LazyArray, denied_partial_mitigations: LazyArray, @@ -389,14 +395,14 @@ macro_rules! define_tables { ) => { #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct LazyTables { - $($name1: LazyTable<$IDX1, $T1>,)+ - $($name2: LazyTable<$IDX2, Option<$T2>>,)+ + $($name1: LazyTableSingleIdx<$IDX1, $T1>,)+ + $($name2: LazyTableSingleIdx<$IDX2, Option<$T2>>,)+ } #[derive(Default)] struct TableBuilders { - $($name1: TableBuilder<$IDX1, $T1>,)+ - $($name2: TableBuilder<$IDX2, Option<$T2>>,)+ + $($name1: TableBuilderSingleIdx<$IDX1, $T1>,)+ + $($name2: TableBuilderSingleIdx<$IDX2, Option<$T2>>,)+ } impl TableBuilders { diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 7b53ebba8adfc..c023b61d73571 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -427,34 +427,38 @@ impl FixedSizeEncoding for Option> { } /// Helper for constructing a table's serialization (also see `Table`). -pub(super) struct TableBuilder { +pub(super) struct TableBuilder { width: usize, - blocks: IndexVec, - _marker: PhantomData, + blocks: IndexVec, + _marker: PhantomData<(IdxDecode, T)>, } -impl Default for TableBuilder { +pub(super) type TableBuilderSingleIdx = TableBuilder; + +impl Default for TableBuilder { fn default() -> Self { TableBuilder { width: 0, blocks: Default::default(), _marker: PhantomData } } } -impl TableBuilder> +impl TableBuilder> where Option: FixedSizeEncoding, { - pub(crate) fn set_some(&mut self, i: I, value: T) { + pub(crate) fn set_some(&mut self, i: Ie, value: T) { self.set(i, Some(value)) } } -impl> TableBuilder { +impl> + TableBuilder +{ /// Sets the table value if it is not default. /// ATTENTION: For optimization default values are simply ignored by this function, because /// right now metadata tables never need to reset non-default values to default. If such need /// arises in the future then a new method (e.g. `clear` or `reset`) will need to be introduced /// for doing that explicitly. - pub(crate) fn set(&mut self, i: I, value: T) { + pub(crate) fn set(&mut self, i: Ie, value: T) { #[cfg(debug_assertions)] { debug_assert!( @@ -477,7 +481,7 @@ impl> TableBui } } - pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { + pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { let pos = buf.position(); let width = self.width; @@ -500,13 +504,17 @@ fn trailing_zeros(x: &[u8]) -> usize { x.iter().rev().take_while(|b| **b == 0).count() } -impl + ParameterizedOverTcx> - LazyTable +impl< + Ie: Idx, + Id: Idx, + const N: usize, + T: FixedSizeEncoding + ParameterizedOverTcx, +> LazyTable where for<'tcx> T::Value<'tcx>: FixedSizeEncoding, { /// Given the metadata, extract out the value at a particular index (if any). - pub(super) fn get<'a, 'tcx, M: MetaBlob<'a>>(&self, metadata: M, i: I) -> T::Value<'tcx> { + pub(super) fn get<'a, 'tcx, M: MetaBlob<'a>>(&self, metadata: M, i: Id) -> T::Value<'tcx> { // Access past the end of the table returns a Default if i.index() >= self.len { return Default::default(); diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 543ad177c370e..ccb6139eae652 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1328,18 +1328,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { enable_feature: self.tcx().sess.is_nightly_build(), }) } - ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => { - self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst { - span, - name, - param_kind: is_type, - help: self.tcx.sess.is_nightly_build() - && !self.tcx.features().gca_min_const_items(), - is_gca, - help_gca: is_gca, - help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca, - }) - } + ResolutionError::ParamInNonTrivialAnonConst { + is_gca_const_items, + name, + param_kind, + } => self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst { + span, + name, + param_kind, + help: self.tcx.sess.is_nightly_build() && !self.tcx.features().gca(), + is_gca_const_items, + help_gca: is_gca_const_items, + help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca_const_items, + }), ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => { self.dcx().create_err(diagnostics::ParamInEnumDiscriminant { span, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index ae4f7cabbe87f..c0e687fc94a38 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -409,7 +409,7 @@ pub(crate) struct SelfInConstGenericTy { #[derive(Diagnostic)] #[diag( - "{$is_gca -> + "{$is_gca_const_items -> [true] generic parameters in const blocks are not allowed; use a named `const` item instead *[false] generic parameters may not be used in const operations }" @@ -423,7 +423,7 @@ pub(crate) struct ParamInNonTrivialAnonConst { pub(crate) param_kind: ParamKindInNonTrivialAnonConst, #[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] pub(crate) help: bool, - pub(crate) is_gca: bool, + pub(crate) is_gca_const_items: bool, #[help( "consider factoring the expression into a `type const` item and use it as the const argument instead" )] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 1fcc4dafeed91..6a5a73715c840 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1659,7 +1659,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.gca_const_items(), + is_gca_const_items: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1751,7 +1751,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.gca_const_items(), + is_gca_const_items: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8eb2aea8a2604..620e6d3cd9ac6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,6 +12,7 @@ use std::debug_assert_matches; use std::mem::{replace, swap, take}; use std::ops::{ControlFlow, Range}; +use rustc_ast::attr::AttributeExt; use rustc_ast::visit::{ AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list, }; @@ -2860,10 +2861,22 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } fn resolve_item(&mut self, item: &'ast Item) { - let mod_inner_docs = - matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs); - if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) { - self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); + match item.kind { + ItemKind::Mod(..) => { + // We only handle outer doc comments for modules here. + let attrs = if let Some(pos) = item.attrs.iter().position(|a| { + a.doc_resolution_scope().is_some_and(|style| style == AttrStyle::Inner) + }) { + &item.attrs[..pos] + } else { + &item.attrs + }; + self.resolve_doc_links(attrs, MaybeExported::Ok(item.id)); + } + ItemKind::Impl(..) | ItemKind::Use(..) => {} + _ => { + self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); + } } debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind); @@ -2957,9 +2970,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let orig_module = replace(&mut self.parent_scope.module, module); self.with_rib(ValueNS, RibKind::Module(module.expect_local()), |this| { this.with_rib(TypeNS, RibKind::Module(module.expect_local()), |this| { - if mod_inner_docs { - this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); - } + // Outer doc comments were already handled above, now we handle + // inner doc comments. + let attrs = if let Some(pos) = item.attrs.iter().position(|a| { + a.doc_resolution_scope().is_some_and(|style| style == AttrStyle::Inner) + }) { + &item.attrs[pos..] + } else { + &[] + }; + this.resolve_doc_links(attrs, MaybeExported::Ok(item.id)); let old_macro_rules = this.parent_scope.macro_rules; visit::walk_item(this, item); // Maintain macro_rules scopes in the same way as during early resolution @@ -5232,7 +5252,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) | AnonConstKind::ArrayLength => { if self.r.features.generic_const_exprs() - || self.r.features.gca_min_const_items() + || self.r.features.gca() || is_trivial_const_arg { ConstantHasGenerics::Yes diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3a72a88f52c1c..e0a3b78fa5e2e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4163,9 +4163,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, - help: self.r.tcx.sess.is_nightly_build() - && !self.r.features.gca_min_const_items(), - is_gca: self.r.features.gca_const_items(), + help: self.r.tcx.sess.is_nightly_build() && !self.r.features.gca(), + is_gca_const_items: self.r.features.gca_const_items(), help_gca: self.r.features.gca_const_items(), help_suggest_gca: self.r.tcx.sess.is_nightly_build() && !self.r.features.gca_const_items(), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f0005d4a98e13..772fdb8c9f14d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -304,7 +304,7 @@ enum ResolutionError<'ra> { /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { - is_gca: bool, + is_gca_const_items: bool, name: Symbol, param_kind: ParamKindInNonTrivialAnonConst, }, diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index ddf5600f76659..ac463297ad84d 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -9,9 +9,9 @@ use pulldown_cmark::{ }; use rustc_ast as ast; use rustc_ast::attr::AttributeExt; -use rustc_ast::join_path_syms; use rustc_ast::token::DocFragmentKind; use rustc_ast::util::comments::beautify_doc_string; +use rustc_ast::{AttrStyle, join_path_syms}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; use rustc_middle::ty::TyCtxt; @@ -48,6 +48,7 @@ pub struct DocFragment { /// Because we tamper with the spans context, this information cannot be correctly retrieved /// later on. So instead, we compute it and store it here. pub from_expansion: bool, + pub style: AttrStyle, } #[derive(Clone, Copy, Debug)] @@ -215,8 +216,15 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( (value_span.with_ctxt(attr_span.ctxt()), value_span.from_expansion()) } }; - let fragment = - DocFragment { span, doc, kind: fragment_kind, item_id, indent: 0, from_expansion }; + let fragment = DocFragment { + span, + doc, + kind: fragment_kind, + item_id, + indent: 0, + from_expansion, + style: attr.doc_resolution_scope().unwrap(), + }; doc_fragments.push(fragment); } else if !doc_only { other_attrs.push(attr.clone()); @@ -231,6 +239,14 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( (doc_fragments, other_attrs) } +/// Represents a doc comment, split in two parts, outer and inner attributes. It's needed for +/// the intra-doc link resolution context. +#[derive(Default)] +pub struct DocStrings { + pub outer: String, + pub inner: String, +} + /// Return the doc-comments on this item, grouped by the module they came from. /// The module can be different if this is a re-export with added documentation. /// @@ -238,11 +254,16 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( /// early and late doc link resolution regardless of their position. pub fn prepare_to_doc_link_resolution( doc_fragments: &[DocFragment], -) -> FxIndexMap, String> { - let mut res = FxIndexMap::default(); +) -> FxIndexMap, DocStrings> { + let mut res: FxIndexMap, DocStrings> = FxIndexMap::default(); for fragment in doc_fragments { - let out_str = res.entry(fragment.item_id).or_default(); - add_doc_fragment(out_str, fragment); + let out_strs = res.entry(fragment.item_id).or_default(); + let out = if fragment.style == AttrStyle::Inner { + &mut out_strs.inner + } else { + &mut out_strs.outer + }; + add_doc_fragment(out, fragment); } res } @@ -351,19 +372,6 @@ pub fn strip_generics_from_path(path_str: &str) -> Result, MalformedGen } } -/// Returns whether the first doc-comment is an inner attribute. -/// -/// If there are no doc-comments, return true. -/// FIXME(#78591): Support both inner and outer attributes on the same item. -pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool { - for attr in attrs { - if let Some(attr_style) = attr.doc_resolution_scope() { - return attr_style == ast::AttrStyle::Inner; - } - } - true -} - /// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]` or `#[doc(attribute)]`. pub fn has_primitive_or_keyword_or_attribute_docs(attrs: &[impl AttributeExt]) -> bool { for attr in attrs { @@ -413,7 +421,10 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec Edition { +pub fn parse_crate_edition( + early_dcx: &EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Edition { + let is_nightly = nightly_options::match_is_nightly_build(matches); + let edition_list = if is_nightly { EDITION_NAME_LIST } else { EDITION_NAME_LIST_STABLE }; let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { early_dcx.early_fatal(format!( - "argument for `--edition` must be one of: \ - {EDITION_NAME_LIST}. (instead was `{arg}`)" + "argument for `--edition` must be one of: {edition_list} (instead was `{arg}`)", )) }), - None => DEFAULT_EDITION, + None => { + if has_input { + eprintln!( + "`--edition` is unspecified, defaulting to `{DEFAULT_EDITION}` while the \ + latest is `{LATEST_STABLE_EDITION}`; it must be one of: {edition_list}\n", + ); + } + DEFAULT_EDITION + } }; if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { - let is_nightly = nightly_options::match_is_nightly_build(matches); let msg = if !is_nightly { format!( - "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}" + "the crate requires edition {edition}, but the latest edition supported by this \ + Rust version is {LATEST_STABLE_EDITION}" ) } else { format!("edition {edition} is unstable and only available with -Z unstable-options") @@ -2681,10 +2696,14 @@ fn parse_remap_path_prefix( // JUSTIFICATION: before wrapper fn is available #[allow(rustc::bad_opt_access)] -pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options { +pub fn build_session_options( + early_dcx: &mut EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Options { let color = parse_color(early_dcx, matches); - let edition = parse_crate_edition(early_dcx, matches); + let edition = parse_crate_edition(early_dcx, matches, has_input); let crate_name = matches.opt_str("crate-name"); let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref()); @@ -2852,14 +2871,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf { early_dcx.early_fatal( "`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \ - and a nightly compiler", + and a nightly compiler", ) } if !nightly_options::is_unstable_enabled(matches) && !unstable_opts.offload.is_empty() { early_dcx.early_fatal( - "`-Zoffload=Enable` also requires `-Zunstable-options` \ - and a nightly compiler", + "`-Zoffload=Enable` also requires `-Zunstable-options` and a nightly compiler", ) } @@ -2875,8 +2893,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if let Some(flavor) = cg.linker_flavor { if flavor.is_unstable() { early_dcx.early_fatal(format!( - "the linker flavor `{}` is unstable, the `-Z unstable-options` \ - flag must also be passed to use the unstable values", + "the linker flavor `{}` is unstable, the `-Z unstable-options` flag must also \ + be passed to use the unstable values", flavor.desc() )); } diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 38165f511b417..d4f3f0e208e34 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -45,7 +45,10 @@ pub const ALL_EDITIONS: &[Edition] = &[ Edition::EditionFuture, ]; +/// All the valid editions that `--edition` will accept on nightly. pub const EDITION_NAME_LIST: &str = "<2015|2018|2021|2024|future>"; +/// All the valid editions on stable, which doesn't include `future`. +pub const EDITION_NAME_LIST_STABLE: &str = "<2015|2018|2021|2024>"; pub const DEFAULT_EDITION: Edition = Edition::Edition2015; @@ -53,13 +56,7 @@ pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2024; impl fmt::Display for Edition { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - Edition::Edition2015 => "2015", - Edition::Edition2018 => "2018", - Edition::Edition2021 => "2021", - Edition::Edition2024 => "2024", - Edition::EditionFuture => "future", - }; + let s = self.as_str(); write!(f, "{s}") } } @@ -75,6 +72,16 @@ impl Edition { } } + pub fn as_str(&self) -> &'static str { + match *self { + Edition::Edition2015 => "2015", + Edition::Edition2018 => "2018", + Edition::Edition2021 => "2021", + Edition::Edition2024 => "2024", + Edition::EditionFuture => "future", + } + } + pub fn is_stable(self) -> bool { match self { Edition::Edition2015 => true, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a39fd0955c344..3debf3248ff80 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1073,6 +1073,7 @@ symbols! { future_trait, fxsr, gca, + gca_adts, gca_const_items, gca_macroless_args, gca_macroless_items, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index c03ace331208b..ed0ecf459c3b8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3985,8 +3985,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, span: Span, ) -> Result, ErrorGuaranteed> { - if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca_min_const_items() - { + if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca() { let guar = self .dcx() .struct_span_err(span, "constant expression depends on a generic parameter") diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index bbaf683f4288a..a5cb7d0c7bb1a 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -12,6 +12,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(deref_patterns)] @@ -20,7 +21,6 @@ #![feature(iterator_try_reduce)] #![feature(option_into_flat_iter)] #![feature(try_blocks)] -#![feature(unwrap_infallible)] #![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc // tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 3ccdb3c8f737c..4e2a863c23bb8 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::solve::inspect::ProbeKind; -use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal}; +use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal, ParamEnvSource}; use rustc_infer::traits::{ BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause, PolyTraitObligation, Selection, SelectionError, SelectionResult, @@ -92,8 +92,8 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( victim: &inspect::InspectCandidate<'_, 'tcx>, other: &inspect::InspectCandidate<'_, 'tcx>, ) -> bool { - // Don't winnow until `Certainty::Yes` -- we don't need to winnow until - // codegen, and only on the good path. + // Don't winnow until `Certainty::Yes` -- we don't need to winnow until constant evaluation or + // codegen. if matches!(other.result().unwrap(), Certainty::Maybe(_)) { return false; } @@ -136,6 +136,15 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( victim.goal().infcx().tcx.specializes((other_def_id, victim_def_id)) } + // Prefer impl candidates over global where clause candidates. Unless `generic_const_args` + // is enabled, we currently don't use an empty environment when resolving and evaluating + // constants to lower them to patterns. If we don't drop where clause candidates here, we + // can fail to select impl candidates (#162331). + ( + CandidateSource::ParamEnv(ParamEnvSource::Global), + CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_), + ) => true, + _ => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 9acc0682e6641..242aa260b8372 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -84,7 +84,7 @@ pub fn is_const_evaluatable<'tcx>( } _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), } - } else if tcx.features().gca_min_const_items() { + } else if tcx.features().gca() { // This is a sanity check to make sure that non-generics consts are checked to // be evaluatable in case they aren't cchecked elsewhere. This will NOT error // if the const uses generics, as desired. diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 449f349aaf886..1d57fd9e4b285 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -749,6 +749,15 @@ fn receiver_is_dispatchable<'tcx>( let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args); clauses.push(trait_predicate.upcast(tcx)); + // U satisfies `Trait`'s where-bounds. + clauses.extend( + tcx.clauses_of(trait_def_id) + .instantiate(tcx, args) + .clauses + .into_iter() + .map(Unnormalized::skip_norm_wip), + ); + let meta_sized_predicate = { let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP); ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 955ab1799a794..ba463184a41f8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1169,7 +1169,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::ConstKind::Value(val) => { // FIXME(mgca): no need to feature-gate once valtree lifetimes are not erased - if tcx.features().gca_min_const_items() { + if tcx.features().gca() { match val.ty.kind() { ty::Adt(adt_def, args) => { let adt_val = val.destructure_adt_const(); diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index d969cca3dcda2..1ef498f072f22 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -280,9 +280,6 @@ pub enum AnonConstKind { /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters - /// - /// under `feature(gca_min_const_items)`, these may be inline consts as well, and should be - /// treated the same as anon consts. MCG, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index de6830a514656..4fb34ed5b2668 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -186,7 +186,6 @@ #![feature(ub_checks)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unwrap_infallible)] #![feature(write_all_vectored)] #![feature(wtf8_internals)] // tidy-alphabetical-end @@ -230,12 +229,25 @@ // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] +#[cfg(not(no_rc))] +#[stable(feature = "rust1", since = "1.0.0")] +pub use rcs::rc; + // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] mod macros; mod raw_vec; +/// Implementations of reference-counted pointers. +#[cfg(not(no_rc))] +mod rcs { + pub mod rc; + + #[cfg(all(not(no_sync), target_has_atomic = "ptr"))] + pub(crate) mod arc; +} + // Heaps provided for low-level allocation strategies pub mod alloc; @@ -256,8 +268,6 @@ pub mod intrinsics; #[unstable(feature = "alloc_io", issue = "154046")] pub mod io; pub mod panicking; -#[cfg(not(no_rc))] -pub mod rc; pub mod slice; pub mod str; pub mod string; diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs new file mode 100644 index 0000000000000..e61ea5193eccb --- /dev/null +++ b/library/alloc/src/rcs/arc.rs @@ -0,0 +1,5204 @@ +use core::any::Any; +use core::cell::CloneFromCell; +#[cfg(not(no_global_oom_handling))] +use core::clone::TrivialClone; +use core::clone::{CloneToUninit, Share, UseCloned}; +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +use core::intrinsics::abort; +#[cfg(not(no_global_oom_handling))] +use core::iter; +use core::marker::{PhantomData, Unsize}; +use core::mem::{self, Alignment, ManuallyDrop}; +use core::num::NonZeroUsize; +use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; +#[cfg(not(no_global_oom_handling))] +use core::ops::{Residual, Try}; +use core::panic::{RefUnwindSafe, UnwindSafe}; +use core::pin::{Pin, PinSafePointer}; +use core::ptr::{self, NonNull}; +#[cfg(not(no_global_oom_handling))] +use core::slice::from_raw_parts_mut; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use core::sync::atomic::{self, Atomic}; +use core::{borrow, fmt, hint}; + +use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::{AllocatorNightly, handle_alloc_error}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::rc::is_dangling; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +/// A soft limit on the amount of references that may be made to an `Arc`. +/// +/// Going above this limit will abort your program (although not +/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. +/// Trying to go above it might call a `panic` (if not actually going above it). +/// +/// This is a global invariant, and also applies when using a compare-exchange loop. +/// +/// See comment in `Arc::clone`. +const MAX_REFCOUNT: usize = (isize::MAX) as usize; + +#[cold] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] +#[cfg_attr(panic = "immediate-abort", inline)] +#[track_caller] +fn panic_arc_overflow() -> ! { + panic!("Arc counter overflow"); +} + +#[cfg(not(sanitize = "thread"))] +macro_rules! acquire { + ($x:expr) => { + atomic::fence(Acquire) + }; +} + +// ThreadSanitizer does not support memory fences. To avoid false positive +// reports in Arc / Weak implementation use atomic loads for synchronization +// instead. +#[cfg(sanitize = "thread")] +macro_rules! acquire { + ($x:expr) => { + $x.load(Acquire) + }; +} + +/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically +/// Reference Counted'. +/// +/// The type `Arc` provides shared ownership of a value of type `T`, +/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces +/// a new `Arc` instance, which points to the same allocation on the heap as the +/// source `Arc`, while increasing a reference count. When the last `Arc` +/// pointer to a given allocation is destroyed, the value stored in that allocation (often +/// referred to as "inner value") is also dropped. +/// +/// Shared references in Rust disallow mutation by default, and `Arc` is no +/// exception: you cannot generally obtain a mutable reference to something +/// inside an `Arc`. If you do need to mutate through an `Arc`, you have several options: +/// +/// 1. Use interior mutability with synchronization primitives like [`Mutex`][mutex], +/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. +/// +/// 2. Use clone-on-write semantics with [`Arc::make_mut`] which provides efficient mutation +/// without requiring interior mutability. This approach clones the data only when +/// needed (when there are multiple references) and can be more efficient when mutations +/// are infrequent. +/// +/// 3. Use [`Arc::get_mut`] when you know your `Arc` is not shared (has a reference count of 1), +/// which provides direct mutable access to the inner value without any cloning. +/// +/// ``` +/// use std::sync::Arc; +/// +/// let mut data = Arc::new(vec![1, 2, 3]); +/// +/// // This will clone the vector only if there are other references to it +/// Arc::make_mut(&mut data).push(4); +/// +/// assert_eq!(*data, vec![1, 2, 3, 4]); +/// ``` +/// +/// **Note**: This type is only available on platforms that support atomic +/// loads and stores of pointers, which includes all platforms that support +/// the `std` crate but not all those which only support [`alloc`](crate). +/// This may be detected at compile time using `#[cfg(target_has_atomic = "ptr")]`. +/// +/// ## Thread Safety +/// +/// Unlike [`Rc`], `Arc` uses atomic operations for its reference +/// counting. This means that it is thread-safe. The disadvantage is that +/// atomic operations are more expensive than ordinary memory accesses. If you +/// are not sharing reference-counted allocations between threads, consider using +/// [`Rc`] for lower overhead. [`Rc`] is a safe default, because the +/// compiler will catch any attempt to send an [`Rc`] between threads. +/// However, a library might choose `Arc` in order to give library consumers +/// more flexibility. +/// +/// `Arc` will implement [`Send`] and [`Sync`] as long as the `T` implements +/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an +/// `Arc` to make it thread-safe? This may be a bit counter-intuitive at +/// first: after all, isn't the point of `Arc` thread safety? The key is +/// this: `Arc` makes it thread safe to have multiple ownership of the same +/// data, but it doesn't add thread safety to its data. Consider +/// Arc<[RefCell\]>. [`RefCell`] isn't [`Sync`], and if `Arc` was always +/// [`Send`], Arc<[RefCell\]> would be as well. But then we'd have a problem: +/// [`RefCell`] is not thread safe; it keeps track of the borrowing count using +/// non-atomic operations. +/// +/// In the end, this means that you may need to pair `Arc` with some sort of +/// [`std::sync`] type, usually [`Mutex`][mutex]. +/// +/// ## Breaking cycles with `Weak` +/// +/// The [`downgrade`][downgrade] method can be used to create a non-owning +/// [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d +/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has +/// already been dropped. In other words, `Weak` pointers do not keep the value +/// inside the allocation alive; however, they *do* keep the allocation +/// (the backing store for the value) alive. +/// +/// A cycle between `Arc` pointers will never be deallocated. For this reason, +/// [`Weak`] is used to break cycles. For example, a tree could have +/// strong `Arc` pointers from parent nodes to children, and [`Weak`] +/// pointers from children back to their parents. +/// +/// # Cloning references +/// +/// Creating a new reference from an existing reference-counted pointer is done using the +/// `Clone` trait implemented for [`Arc`][Arc] and [`Weak`][Weak]. +/// +/// ``` +/// use std::sync::Arc; +/// let foo = Arc::new(vec![1.0, 2.0, 3.0]); +/// // The two syntaxes below are equivalent. +/// let a = foo.clone(); +/// let b = Arc::clone(&foo); +/// // a, b, and foo are all Arcs that point to the same memory location +/// ``` +/// +/// ## `Deref` behavior +/// +/// `Arc` automatically dereferences to `T` (via the [`Deref`] trait), +/// so you can call `T`'s methods on a value of type `Arc`. To avoid name +/// clashes with `T`'s methods, the methods of `Arc` itself are associated +/// functions, called using [fully qualified syntax]: +/// +/// ``` +/// use std::sync::Arc; +/// +/// let my_arc = Arc::new(()); +/// let my_weak = Arc::downgrade(&my_arc); +/// ``` +/// +/// `Arc`'s implementations of traits like `Clone` may also be called using +/// fully qualified syntax. Some people prefer to use fully qualified syntax, +/// while others prefer using method-call syntax. +/// +/// ``` +/// use std::sync::Arc; +/// +/// let arc = Arc::new(()); +/// // Method-call syntax +/// let arc2 = arc.clone(); +/// // Fully qualified syntax +/// let arc3 = Arc::clone(&arc); +/// ``` +/// +/// [`Weak`][Weak] does not auto-dereference to `T`, because the inner value may have +/// already been dropped. +/// +/// [`Rc`]: crate::rc::Rc +/// [clone]: Clone::clone +/// [mutex]: ../../std/sync/struct.Mutex.html +/// [rwlock]: ../../std/sync/struct.RwLock.html +/// [atomic]: core::sync::atomic +/// [downgrade]: Arc::downgrade +/// [upgrade]: Weak::upgrade +/// [RefCell\]: core::cell::RefCell +/// [`RefCell`]: core::cell::RefCell +/// [`std::sync`]: ../../std/sync/index.html +/// [`Arc::clone(&from)`]: Arc::clone +/// [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name +/// +/// # Examples +/// +/// Sharing some immutable data between threads: +/// +/// ``` +/// use std::sync::Arc; +/// use std::thread; +/// +/// let five = Arc::new(5); +/// +/// for _ in 0..10 { +/// let five = Arc::clone(&five); +/// +/// thread::spawn(move || { +/// println!("{five:?}"); +/// }); +/// } +/// ``` +/// +/// Sharing a mutable [`AtomicUsize`]: +/// +/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize" +/// +/// ``` +/// use std::sync::Arc; +/// use std::sync::atomic::{AtomicUsize, Ordering}; +/// use std::thread; +/// +/// let val = Arc::new(AtomicUsize::new(5)); +/// +/// for _ in 0..10 { +/// let val = Arc::clone(&val); +/// +/// thread::spawn(move || { +/// let v = val.fetch_add(1, Ordering::Relaxed); +/// println!("{v:?}"); +/// }); +/// } +/// ``` +/// +/// See the [`rc` documentation][rc_examples] for more examples of reference +/// counting in general. +/// +/// [rc_examples]: crate::rc#examples +#[doc(search_unbox)] +#[rustc_diagnostic_item = "Arc"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +#[diagnostic::on_move( + message = "the type `{Self}` does not implement `Copy`", + label = "this move could be avoided by cloning the original `{Self}`, which is inexpensive", + note = "consider using `Arc::clone`" +)] +pub struct Arc< + T: ?Sized, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, +> { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Arc {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Arc {} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe + for Arc +{ +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Arc {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Arc {} + +// SAFETY: `Arc::clone` doesn't access any `Cell`s which could contain the `Arc` being cloned. +#[unstable(feature = "cell_get_cloned", issue = "145329")] +unsafe impl CloneFromCell for Arc {} + +impl Arc { + unsafe fn from_inner(ptr: NonNull>) -> Self { + // SAFETY: Upheld by caller. + unsafe { Self::from_inner_in(ptr, Global) } + } + + unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { + // SAFETY: Upheld by caller. + unsafe { Self::from_ptr_in(ptr, Global) } + } +} + +impl Arc { + #[inline] + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); + // SAFETY: Pointer is valid for reads. + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + + #[inline] + unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { + Self { ptr, phantom: PhantomData, alloc } + } + + #[inline] + unsafe fn from_ptr_in(ptr: *mut ArcInner, alloc: A) -> Self { + // SAFETY: Upheld by caller. + unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } + } +} + +/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the +/// managed allocation. +/// +/// The allocation is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [Option]<[Arc]\>. +/// +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. +/// +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Arc`] pointers, since mutual owning references +/// would never allow either [`Arc`] to be dropped. For example, a tree could +/// have strong [`Arc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. +/// +/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`]. +/// +/// [`upgrade`]: Weak::upgrade +#[stable(feature = "arc_weak", since = "1.4.0")] +#[rustc_diagnostic_item = "ArcWeak"] +pub struct Weak< + T: ?Sized, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, +> { + // This is a `NonNull` to allow optimizing the size of this type in enums, + // but it is not necessarily a valid pointer. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real pointer + // will ever have because ArcInner has alignment at least 2. + ptr: NonNull>, + alloc: A, +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Send for Weak {} +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Sync for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Weak {} +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Weak {} + +// SAFETY: `Weak::clone` doesn't access any `Cell`s which could contain the `Weak` being cloned. +#[unstable(feature = "cell_get_cloned", issue = "145329")] +unsafe impl CloneFromCell for Weak {} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(Weak)") + } +} + +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +// Unlike RcInner, repr(align(2)) is not strictly required because atomic types +// have the alignment same as its size, but we use it for consistency and clarity. +#[repr(C, align(2))] +struct ArcInner { + strong: Atomic, + + // the value usize::MAX acts as a sentinel for temporarily "locking" the + // weak count, preventing `Arc::downgrade` from racing to create new + // `Weak` references. `Arc::is_unique` (which backs `Arc::get_mut`) + // needs to observe both the strong and weak counts as indicating + // uniqueness in one logical atomic step; since they live in separate + // atomic words, it locks the weak count while reading the strong + // count to keep the two reads consistent. + weak: Atomic, + + data: T, +} + +/// Calculate layout for `ArcInner` using the inner value's layout +fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + Layout::new::>() + .extend(layout) + .unwrap_or_else(|_| panic!("capacity overflow")) + .0 + .pad_to_align() +} + +unsafe impl Send for ArcInner {} +unsafe impl Sync for ArcInner {} + +impl Arc { + /// Constructs a new `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(data: T) -> Arc { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = Box::new(ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }); + // SAFETY: Pointer is valid. + unsafe { Self::from_inner(Box::into_non_null(x)) } + } + + /// Constructs a new `Arc` while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Arc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic` first allocates the managed allocation for the `Arc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Arc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Example + /// + /// ``` + /// # #![allow(dead_code)] + /// use std::sync::{Arc, Weak}; + /// + /// struct Gadget { + /// me: Weak, + /// } + /// + /// impl Gadget { + /// /// Constructs a reference counted Gadget. + /// fn new() -> Arc { + /// // `me` is a `Weak` pointing at the new allocation of the + /// // `Arc` we're constructing. + /// Arc::new_cyclic(|me| { + /// // Create the actual struct here. + /// Gadget { me: me.clone() } + /// }) + /// } + /// + /// /// Returns a reference counted pointer to Self. + /// fn me(&self) -> Arc { + /// self.me.upgrade().unwrap() + /// } + /// } + /// ``` + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "arc_new_cyclic", since = "1.60.0")] + pub fn new_cyclic(data_fn: F) -> Arc + where + F: FnOnce(&Weak) -> T, + { + Self::new_cyclic_in(data_fn, Global) + } + + /// Constructs a new `Arc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit() -> Arc> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + <*mut u8>::cast, + )) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let zero = Arc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] + #[must_use] + pub fn new_zeroed() -> Arc> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + <*mut u8>::cast, + )) + } + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `data` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "pin", since = "1.33.0")] + #[must_use] + pub fn pin(data: T) -> Pin> { + // SAFETY: We own and create the pinned pointer. + unsafe { Pin::new_unchecked(Arc::new(data)) } + } + + /// Constructs a new `Pin>`, return an error if allocation fails. + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn try_pin(data: T) -> Result>, AllocError> { + // SAFETY: We own and create the pinned pointer. + unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } + } + + /// Constructs a new `Arc`, returning an error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// use std::sync::Arc; + /// + /// let five = Arc::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn try_new(data: T) -> Result, AllocError> { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = Box::try_new(ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + })?; + // SAFETY: Pointer is valid. + unsafe { Ok(Self::from_inner(Box::into_non_null(x))) } + } + + /// Constructs a new `Arc` with uninitialized contents, returning an error + /// if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::try_new_uninit()?; + /// + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn try_new_uninit() -> Result>, AllocError> { + // ignore-tidy-undocumented-unsafe + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + <*mut u8>::cast, + )?)) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if allocation fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature( allocator_ext)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn try_new_zeroed() -> Result>, AllocError> { + // ignore-tidy-undocumented-unsafe + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + <*mut u8>::cast, + )?)) + } + } +} + +impl Arc { + /// Constructs a new `Arc` in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::new_in(5, System); + /// ``` + #[inline] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn new_in(data: T, alloc: A) -> Arc { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x = Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + ); + let (ptr, alloc) = Box::into_non_null_with_allocator(x); + // SAFETY: Pointer is valid. + unsafe { Self::from_inner_in(ptr, alloc) } + } + + /// Constructs a new `Arc` with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let mut five = Arc::::new_uninit_in(System); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn new_uninit_in(alloc: A) -> Arc, A> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::from_ptr_in( + Arc::allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate(layout), + <*mut u8>::cast, + ), + alloc, + ) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let zero = Arc::::new_zeroed_in(System); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn new_zeroed_in(alloc: A) -> Arc, A> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::from_ptr_in( + Arc::allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate_zeroed(layout), + <*mut u8>::cast, + ), + alloc, + ) + } + } + + /// Constructs a new `Arc` in the given allocator while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Arc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic_in` first allocates the managed allocation for the `Arc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Arc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic_in` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Example + /// + /// See [`new_cyclic`] + /// + /// [`new_cyclic`]: Arc::new_cyclic + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn new_cyclic_in(data_fn: F, alloc: A) -> Arc + where + F: FnOnce(&Weak) -> T, + { + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let (uninit_ptr, alloc) = Box::into_non_null_with_allocator(Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + weak: atomic::AtomicUsize::new(1), + data: mem::MaybeUninit::::uninit(), + }, + alloc, + )); + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr, alloc }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + // Now we can properly initialize the inner value and turn our weak + // reference into a strong reference. + let inner = init_ptr.as_ptr(); + // ignore-tidy-undocumented-unsafe + unsafe { + ptr::write(&raw mut (*inner).data, data); + + // The above write to the data field must be visible to any threads which + // observe a non-zero strong count. Therefore we need at least "Release" ordering + // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`. + // + // "Acquire" ordering is not required. When considering the possible behaviors + // of `data_fn` we only need to look at what it could do with a reference to a + // non-upgradeable `Weak`: + // - It can *clone* the `Weak`, increasing the weak reference count. + // - It can drop those clones, decreasing the weak reference count (but never to zero). + // + // These side effects do not impact us in any way, and no other side effects are + // possible with safe code alone. + let prev_value = (*inner).strong.fetch_add(1, Release); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + // Calling into_raw_with_allocator has the double effect of giving us back the allocator, + // and forgetting the weak reference. + let alloc = weak.into_raw_with_allocator().1; + + Arc::from_inner_in(init_ptr, alloc) + } + } + + /// Constructs a new `Pin>` in the provided allocator. If `T` does not implement `Unpin`, + /// then `data` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn pin_in(data: T, alloc: A) -> Pin> + where + A: StaticAllocator, + { + // SAFETY: We own and create the pinned pointer. + unsafe { Pin::new_unchecked(Arc::new_in(data, alloc)) } + } + + /// Constructs a new `Pin>` in the provided allocator, return an error if allocation + /// fails. + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn try_pin_in(data: T, alloc: A) -> Result>, AllocError> + where + A: StaticAllocator, + { + // SAFETY: We own and create the pinned pointer. + unsafe { Ok(Pin::new_unchecked(Arc::try_new_in(data, alloc)?)) } + } + + /// Constructs a new `Arc` in the provided allocator, returning an error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::try_new_in(5, System)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn try_new_in(data: T, alloc: A) -> Result, AllocError> { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x = Box::try_new_in( + ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + )?; + let (ptr, alloc) = Box::into_non_null_with_allocator(x); + // SAFETY: Pointer is valid since we created it. + Ok(unsafe { Self::from_inner_in(ptr, alloc) }) + } + + /// Constructs a new `Arc` with uninitialized contents, in the provided allocator, returning an + /// error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let mut five = Arc::::try_new_uninit_in(System)?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + // ignore-tidy-undocumented-unsafe + unsafe { + Ok(Arc::from_ptr_in( + Arc::try_allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate(layout), + <*mut u8>::cast, + )?, + alloc, + )) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, in the provided allocator, returning an error if allocation + /// fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let zero = Arc::::try_new_zeroed_in(System)?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + // ignore-tidy-undocumented-unsafe + unsafe { + Ok(Arc::from_ptr_in( + Arc::try_allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate_zeroed(layout), + <*mut u8>::cast, + )?, + alloc, + )) + } + } + /// Returns the inner value, if the `Arc` has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same `Arc` that was + /// passed in. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// It is strongly recommended to use [`Arc::into_inner`] instead if you don't + /// keep the `Arc` in the [`Err`] case. + /// Immediately dropping the [`Err`]-value, as the expression + /// `Arc::try_unwrap(this).ok()` does, can cause the strong count to + /// drop to zero and the inner value of the `Arc` to be dropped. + /// For instance, if two threads execute such an expression in parallel, + /// there is a race condition without the possibility of unsafety: + /// The threads could first both check whether they own the last instance + /// in `Arc::try_unwrap`, determine that they both do not, and then both + /// discard and drop their instance in the call to [`ok`][`Result::ok`]. + /// In this scenario, the value inside the `Arc` is safely destroyed + /// by exactly one of the threads, but neither thread will ever be able + /// to use the value. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// assert_eq!(Arc::try_unwrap(x), Ok(3)); + /// + /// let x = Arc::new(4); + /// let _y = Arc::clone(&x); + /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn try_unwrap(this: Self) -> Result { + if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() { + return Err(this); + } + + acquire!(this.inner().strong); + + let this = ManuallyDrop::new(this); + // SAFETY: Pointer is valid for reads, contains initialised memory, + // and not dropped multiple times (we return it). + let elem: T = unsafe { ptr::read(&this.ptr.as_ref().data) }; + // SAFETY: As above, but we explicitly drop the allocator only once + // upon creating and dropping a weak pointer. + let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator + + // Make a weak pointer to clean up the implicit strong-weak reference + let _weak = Weak { ptr: this.ptr, alloc }; + + Ok(elem) + } + + /// Returns the inner value, if the `Arc` has exactly one strong reference. + /// + /// Otherwise, [`None`] is returned and the `Arc` is dropped. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// If `Arc::into_inner` is called on every clone of this `Arc`, + /// it is guaranteed that exactly one of the calls returns the inner value. + /// This means in particular that the inner value is not dropped. + /// + /// [`Arc::try_unwrap`] is conceptually similar to `Arc::into_inner`, but it + /// is meant for different use-cases. If used as a direct replacement + /// for `Arc::into_inner` anyway, such as with the expression + /// [Arc::try_unwrap]\(this).[ok][Result::ok](), then it does + /// **not** give the same guarantee as described in the previous paragraph. + /// For more information, see the examples below and read the documentation + /// of [`Arc::try_unwrap`]. + /// + /// # Examples + /// + /// Minimal example demonstrating the guarantee that `Arc::into_inner` gives. + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// let y = Arc::clone(&x); + /// + /// // Two threads calling `Arc::into_inner` on both clones of an `Arc`: + /// let x_thread = std::thread::spawn(|| Arc::into_inner(x)); + /// let y_thread = std::thread::spawn(|| Arc::into_inner(y)); + /// + /// let x_inner_value = x_thread.join().unwrap(); + /// let y_inner_value = y_thread.join().unwrap(); + /// + /// // One of the threads is guaranteed to receive the inner value: + /// assert!(matches!( + /// (x_inner_value, y_inner_value), + /// (None, Some(3)) | (Some(3), None) + /// )); + /// // The result could also be `(None, None)` if the threads called + /// // `Arc::try_unwrap(x).ok()` and `Arc::try_unwrap(y).ok()` instead. + /// ``` + /// + /// A more practical example demonstrating the need for `Arc::into_inner`: + /// ``` + /// use std::sync::Arc; + /// + /// // Definition of a simple singly linked list using `Arc`: + /// #[derive(Clone)] + /// struct LinkedList(Option>>); + /// struct Node(T, Option>>); + /// + /// // Dropping a long `LinkedList` relying on the destructor of `Arc` + /// // can cause a stack overflow. To prevent this, we can provide a + /// // manual `Drop` implementation that does the destruction in a loop: + /// impl Drop for LinkedList { + /// fn drop(&mut self) { + /// let mut link = self.0.take(); + /// while let Some(arc_node) = link.take() { + /// if let Some(Node(_value, next)) = Arc::into_inner(arc_node) { + /// link = next; + /// } + /// } + /// } + /// } + /// + /// // Implementation of `new` and `push` omitted + /// impl LinkedList { + /// /* ... */ + /// # fn new() -> Self { + /// # LinkedList(None) + /// # } + /// # fn push(&mut self, x: T) { + /// # self.0 = Some(Arc::new(Node(x, self.0.take()))); + /// # } + /// } + /// + /// // The following code could have still caused a stack overflow + /// // despite the manual `Drop` impl if that `Drop` impl had used + /// // `Arc::try_unwrap(arc).ok()` instead of `Arc::into_inner(arc)`. + /// + /// // Create a long list and clone it + /// let mut x = LinkedList::new(); + /// let size = 100000; + /// # let size = if cfg!(miri) { 100 } else { size }; + /// for i in 0..size { + /// x.push(i); // Adds i to the front of x + /// } + /// let y = x.clone(); + /// + /// // Drop the clones in parallel + /// let x_thread = std::thread::spawn(|| drop(x)); + /// let y_thread = std::thread::spawn(|| drop(y)); + /// x_thread.join().unwrap(); + /// y_thread.join().unwrap(); + /// ``` + #[inline] + #[stable(feature = "arc_into_inner", since = "1.70.0")] + pub fn into_inner(this: Self) -> Option { + // Make sure that the ordinary `Drop` implementation isn’t called as well + let mut this = mem::ManuallyDrop::new(this); + + // Following the implementation of `drop` and `drop_slow` + if this.inner().strong.fetch_sub(1, Release) != 1 { + return None; + } + + acquire!(this.inner().strong); + + // SAFETY: This mirrors the line + // + // unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) }; + // + // in `drop_slow`. Instead of dropping the value behind the pointer, + // it is read and eventually returned; `ptr::read` has the same + // safety conditions as `ptr::drop_in_place`. + let inner = unsafe { ptr::read(Self::get_mut_unchecked(&mut this)) }; + // SAFETY: Pointer is valid for reads. + let alloc = unsafe { ptr::read(&this.alloc) }; + + drop(Weak { ptr: this.ptr, alloc }); + + Some(inner) + } + + /// Maps the value in an `Arc`, reusing the allocation if possible. + /// + /// `f` is called on a reference to the value in the `Arc`, and the result is returned, also in + /// an `Arc`. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Arc::map(a, f)` instead of `r.map(a)`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let r = Arc::new(7); + /// let new = Arc::map(r, |i| i + 7); + /// assert_eq!(*new, 14); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "smart_pointer_map", since = "CURRENT_RUSTC_VERSION")] + pub fn map(this: Self, f: impl FnOnce(&T) -> U) -> Arc { + if size_of::() == size_of::() + && align_of::() == align_of::() + && Arc::is_unique(&this) + { + // ignore-tidy-undocumented-unsafe + unsafe { + let (ptr, alloc) = Arc::into_raw_with_allocator(this); + let value = ptr.read(); + let mut allocation = Arc::from_raw_in(ptr.cast::>(), alloc); + + Arc::get_mut_unchecked(&mut allocation).write(f(&value)); + allocation.assume_init() + } + } else { + let output = f(&*this); + let (ptr, alloc) = Arc::into_raw_with_allocator(this); + // ignore-tidy-undocumented-unsafe + unsafe { Arc::decrement_strong_count_in(ptr, &alloc) } + + Arc::new_in(output, alloc) + } + } + + /// Attempts to map the value in an `Arc`, reusing the allocation if possible. + /// + /// `f` is called on a reference to the value in the `Arc`, and if the operation succeeds, the + /// result is returned, also in an `Arc`. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Arc::try_map(a, f)` instead of `a.try_map(f)`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// ``` + /// #![feature(smart_pointer_try_map)] + /// + /// use std::sync::Arc; + /// + /// let b = Arc::new(7); + /// let new = Arc::try_map(b, |&i| u32::try_from(i)).unwrap(); + /// assert_eq!(*new, 7); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "smart_pointer_try_map", issue = "144419")] + pub fn try_map( + this: Self, + f: impl FnOnce(&T) -> R, + ) -> >>::TryType + where + R: Try, + R::Residual: Residual>, + { + if size_of::() == size_of::() + && align_of::() == align_of::() + && Arc::is_unique(&this) + { + // ignore-tidy-undocumented-unsafe + unsafe { + let (ptr, alloc) = Arc::into_raw_with_allocator(this); + let value = ptr.read(); + let mut allocation = + Arc::from_raw_in(ptr.cast::>(), alloc); + + Arc::get_mut_unchecked(&mut allocation).write(f(&value)?); + try { allocation.assume_init() } + } + } else { + let output = f(&*this)?; + let (ptr, alloc) = Arc::into_raw_with_allocator(this); + // ignore-tidy-undocumented-unsafe + unsafe { Arc::decrement_strong_count_in(ptr, &alloc) } + + try { Arc::new_in(output, alloc) } + } + } +} + +impl Arc<[T]> { + /// Constructs a new atomically reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// // Deferred initialization: + /// let data = Arc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); + /// + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + // ignore-tidy-undocumented-unsafe + unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } + } + + /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let values = Arc::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] + #[must_use] + pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate_zeroed(layout), + |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[mem::MaybeUninit]>, + )) + } + } +} + +impl Arc<[T], A> { + /// Constructs a new atomically reference-counted slice with uninitialized contents in the + /// provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let mut values = Arc::<[u32], _>::new_uninit_slice_in(3, System); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { + // ignore-tidy-undocumented-unsafe + unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } + } + + /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes, in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let values = Arc::<[u32], _>::new_zeroed_slice_in(3, System); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + #[inline] + pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::from_ptr_in( + Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| alloc.allocate_zeroed(layout), + |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[mem::MaybeUninit]>, + ), + alloc, + ) + } + } + + /// Converts the reference-counted slice into a reference-counted array. + /// + /// This operation does not reallocate; the underlying array of the slice is simply reinterpreted as an array type. + /// + /// # Errors + /// + /// Returns the original `Arc<[T]>` in the `Err` variant if `self.len()` does not equal `N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(alloc_slice_into_array)] + /// use std::sync::Arc; + /// + /// let arc_slice: Arc<[i32]> = Arc::new([1, 2, 3]); + /// + /// let arc_array: Arc<[i32; 3]> = arc_slice.into_array().unwrap(); + /// ``` + #[unstable(feature = "alloc_slice_into_array", issue = "148082")] + #[inline] + pub fn into_array(self) -> Result, Self> { + if self.len() == N { + let (ptr, alloc) = Self::into_raw_with_allocator(self); + let ptr = ptr as *const [T; N]; + + // SAFETY: The underlying array of a slice has the exact same layout as an actual array `[T; N]` if `N` is equal to the slice's length. + let me = unsafe { Arc::from_raw_in(ptr, alloc) }; + Ok(me) + } else { + Err(self) + } + } +} + +impl Arc, A> { + /// Converts to `Arc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub unsafe fn assume_init(self) -> Arc { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + // ignore-tidy-undocumented-unsafe + unsafe { Arc::from_inner_in(ptr.cast(), alloc) } + } +} + +impl Arc { + /// Constructs a new `Arc` with a clone of `value`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clone_from_ref)] + /// use std::sync::Arc; + /// + /// let hello: Arc = Arc::clone_from_ref("hello"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "clone_from_ref", issue = "149075")] + pub fn clone_from_ref(value: &T) -> Arc { + Arc::clone_from_ref_in(value, Global) + } + + /// Constructs a new `Arc` with a clone of `value`, returning an error if allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(clone_from_ref)] + /// use std::sync::Arc; + /// + /// let hello: Arc = Arc::try_clone_from_ref("hello")?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "clone_from_ref", issue = "149075")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn try_clone_from_ref(value: &T) -> Result, AllocError> { + Arc::try_clone_from_ref_in(value, Global) + } +} + +impl Arc { + /// Constructs a new `Arc` with a clone of `value` in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(clone_from_ref)] + /// #![feature(allocator_ext)] + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let hello: Arc = Arc::clone_from_ref_in("hello", System); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "clone_from_ref", issue = "149075")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn clone_from_ref_in(value: &T, alloc: A) -> Arc { + // `in_progress` drops the allocation if we panic before finishing initializing it. + let mut in_progress: UniqueArcUninit = UniqueArcUninit::new(value, alloc); + + // Initialize with clone of value. + // ignore-tidy-undocumented-unsafe + unsafe { + // Clone. If the clone panics, `in_progress` will be dropped and clean up. + value.clone_to_uninit(in_progress.data_ptr().cast()); + // Cast type of pointer, now that it is initialized. + in_progress.into_arc() + } + } + + /// Constructs a new `Arc` with a clone of `value` in the provided allocator, returning an error if allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(clone_from_ref)] + /// #![feature(allocator_ext)] + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let hello: Arc = Arc::try_clone_from_ref_in("hello", System)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "clone_from_ref", issue = "149075")] + //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result, AllocError> { + // `in_progress` drops the allocation if we panic before finishing initializing it. + let mut in_progress: UniqueArcUninit = UniqueArcUninit::try_new(value, alloc)?; + + // Initialize with clone of value. + // ignore-tidy-undocumented-unsafe + let initialized_clone = unsafe { + // Clone. If the clone panics, `in_progress` will be dropped and clean up. + value.clone_to_uninit(in_progress.data_ptr().cast()); + // Cast type of pointer, now that it is initialized. + in_progress.into_arc() + }; + + Ok(initialized_clone) + } +} + +impl Arc<[mem::MaybeUninit], A> { + /// Converts to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// // Deferred initialization: + /// let data = Arc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); + /// + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T], A> { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + // SAFETY: Upheld by caller. + unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } + } +} + +impl Arc { + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator]. + /// + /// # Safety + /// + /// * Creating a `Arc` from a pointer other than one returned from + /// [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator] + /// is undefined behavior. + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// * Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. + /// * The raw pointer must point to a block of memory allocated by the global allocator. + /// * The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Arc` is never accessed. + /// + /// [into_raw]: Arc::into_raw + /// [into_raw_with_allocator]: Arc::into_raw_with_allocator + /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Arc` to prevent leak. + /// let x = Arc::from_raw(x_ptr); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc<[u32]> = Arc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Upheld by caller. + unsafe { Arc::from_raw_in(ptr, Global) } + } + + /// Consumes the `Arc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Arc::from_raw(x_ptr) }); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "rc_raw", since = "1.17.0")] + #[rustc_never_returns_null_ptr] + pub fn into_raw(this: Self) -> *const T { + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) + } + + /// Increments the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method, and `ptr` must point to a block of memory + /// allocated by the global allocator. + /// + /// [from_raw_in]: Arc::from_raw_in + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count(ptr); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Arc::decrement_strong_count(ptr); + /// } + /// ``` + #[inline] + #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] + pub unsafe fn increment_strong_count(ptr: *const T) { + // SAFETY: Upheld by caller. + unsafe { Arc::increment_strong_count_in(ptr, Global) } + } + + /// Decrements the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method, and `ptr` must point to a block of memory + /// allocated by the global allocator. This method can be used to release the final + /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been + /// released. + /// + /// [from_raw_in]: Arc::from_raw_in + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count(ptr); + /// + /// // Those assertions are deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// Arc::decrement_strong_count(ptr); + /// assert_eq!(1, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] + pub unsafe fn decrement_strong_count(ptr: *const T) { + // SAFETY: Upheld by caller. + unsafe { Arc::decrement_strong_count_in(ptr, Global) } + } + + /// Gets the number of strong (`Arc`) pointers to the allocation behind the given raw + /// pointer. + /// + /// This method does not consume or drop the `Arc` behind this pointer. + /// + /// # Safety + /// + /// The pointer must point to (and have valid metadata for) the value inside a live `Arc` + /// allocation, such as a pointer returned by [`Arc::into_raw`], + /// [`Arc::into_raw_with_allocator`], or [`Arc::as_ptr`]. + /// `T` must have the same alignment as that value. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method. + /// + /// Using this method correctly also requires extra care: another thread can change the + /// strong count at any time, including between calling this method and acting on the + /// result. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_raw_get_strong)] + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _also_five = Arc::clone(&five); + /// let ptr = Arc::into_raw(five); + /// + /// unsafe { + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// assert_eq!(2, Arc::strong_count_from_raw(ptr)); + /// + /// // Convert back to an `Arc` to avoid leaking memory. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "arc_raw_get_strong", issue = "157021")] + pub unsafe fn strong_count_from_raw(ptr: *const T) -> usize { + // SAFETY: Upheld by caller. + let offset = unsafe { data_offset(ptr) }; + // Reverse the offset to find the original ArcInner. + // SAFETY: Caller ensures this pointer was to an `Arc` allocation, + // so offsetting must be inbounds. + let arc_ptr = unsafe { ptr.byte_sub(offset) as *mut ArcInner }; + // SAFETY: Per the above, an `ArcInner` is stored here. + unsafe { (*arc_ptr).strong.load(Relaxed) } + } +} + +impl Arc { + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn allocator(this: &Self) -> &A { + &this.alloc + } + + /// Consumes the `Arc`, returning the wrapped pointer and allocator. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw_in`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x = Arc::new_in("hello".to_owned(), System); + /// let (ptr, alloc) = Arc::into_raw_with_allocator(x); + /// assert_eq!(unsafe { &*ptr }, "hello"); + /// let x = unsafe { Arc::from_raw_in(ptr, alloc) }; + /// assert_eq!(&*x, "hello"); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(this); + let ptr = Self::as_ptr(&this); + // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + (ptr, alloc) + } + + /// Provides a raw pointer to the data. + /// + /// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for + /// as long as there are strong counts in the `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let y = Arc::clone(&x); + /// let x_ptr = Arc::as_ptr(&x); + /// assert_eq!(x_ptr, Arc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[must_use] + #[stable(feature = "rc_as_ptr", since = "1.45.0")] + #[rustc_never_returns_null_ptr] + pub fn as_ptr(this: &Self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); + + // SAFETY: This cannot go through Deref::deref or ArcInnerPtr::inner because + // this is required to retain raw/mut provenance such that e.g. `get_mut` can + // write through the pointer after the Arc is recovered through `from_raw`. + unsafe { &raw mut (*ptr).data } + } + + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator]. + /// + /// # Safety + /// + /// * Creating a `Arc` from a pointer other than one returned from + /// [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator] + /// is undefined behavior. + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// * Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. + /// * The raw pointer must point to a block of memory allocated by `alloc` + /// * The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Arc` is never accessed. + /// + /// [into_raw]: Arc::into_raw + /// [into_raw_with_allocator]: Arc::into_raw_with_allocator + /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x = Arc::new_in("hello".to_owned(), System); + /// let (x_ptr, alloc) = Arc::into_raw_with_allocator(x); + /// + /// unsafe { + /// // Convert back to an `Arc` to prevent leak. + /// let x = Arc::from_raw_in(x_ptr, System); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x: Arc<[u32], _> = Arc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Arc::into_raw_with_allocator(x).0; + /// + /// unsafe { + /// let x: Arc<[u32; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + // SAFETY: Upheld by caller. + unsafe { + let offset = data_offset(ptr); + + // Reverse the offset to find the original ArcInner. + let arc_ptr = ptr.byte_sub(offset) as *mut ArcInner; + + Self::from_ptr_in(arc_ptr, alloc) + } + } + + /// Creates a new [`Weak`] pointer to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// ``` + #[must_use = "this returns a new `Weak` pointer, \ + without modifying the original `Arc`"] + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn downgrade(this: &Self) -> Weak + where + A: AllocatorClone, + { + // This Relaxed is OK because we're checking the value in the CAS + // below. + let mut cur = this.inner().weak.load(Relaxed); + + loop { + // check if the weak counter is currently "locked"; if so, spin. + if cur == usize::MAX { + hint::spin_loop(); + cur = this.inner().weak.load(Relaxed); + continue; + } + + // We can't allow the refcount to increase much past `MAX_REFCOUNT`. + if cur > MAX_REFCOUNT { + panic_arc_overflow(); + } + // NOTE: this code currently ignores the possibility of overflow + // into usize::MAX; in general both Rc and Arc need to be adjusted + // to deal with overflow. + + // Unlike with Clone(), we need this to be an Acquire read to + // synchronize with the write coming from `is_unique`, so that the + // events prior to that write happen before this read. + match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { + Ok(_) => { + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr.as_ptr())); + return Weak { ptr: this.ptr, alloc: this.alloc.clone() }; + } + Err(old) => cur = old, + } + } + } + + /// Gets the number of [`Weak`] pointers to this allocation. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the weak count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _weak_five = Arc::downgrade(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` or `Weak` between threads. + /// assert_eq!(1, Arc::weak_count(&five)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn weak_count(this: &Self) -> usize { + let cnt = this.inner().weak.load(Relaxed); + // If the weak count is currently locked, the value of the + // count was 0 just before taking the lock. + if cnt == usize::MAX { 0 } else { cnt - 1 } + } + + /// Gets the number of strong (`Arc`) pointers to this allocation. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the strong count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _also_five = Arc::clone(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// assert_eq!(2, Arc::strong_count(&five)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn strong_count(this: &Self) -> usize { + this.inner().strong.load(Relaxed) + } + + /// Increments the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method, and `ptr` must point to a block of memory + /// allocated by `alloc`. + /// + /// [from_raw_in]: Arc::from_raw_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::new_in(5, System); + /// + /// unsafe { + /// let (ptr, _alloc) = Arc::into_raw_with_allocator(five); + /// Arc::increment_strong_count_in(ptr, System); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw_in(ptr, System); + /// assert_eq!(2, Arc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Arc::decrement_strong_count_in(ptr, System); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A) + where + A: AllocatorClone, + { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + // SAFETY: Upheld by caller. + let arc = unsafe { mem::ManuallyDrop::new(Arc::from_raw_in(ptr, alloc)) }; + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); + } + + /// Decrements the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method, and `ptr` must point to a block of memory + /// allocated by `alloc`. This method can be used to release the final + /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been + /// released. + /// + /// [from_raw_in]: Arc::from_raw_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::new_in(5, System); + /// + /// unsafe { + /// let (ptr, _alloc) = Arc::into_raw_with_allocator(five); + /// Arc::increment_strong_count_in(ptr, System); + /// + /// // Those assertions are deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw_in(ptr, System); + /// assert_eq!(2, Arc::strong_count(&five)); + /// Arc::decrement_strong_count_in(ptr, System); + /// assert_eq!(1, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { + // SAFETY: Upheld by caller. + unsafe { drop(Arc::from_raw_in(ptr, alloc)) }; + } + + #[inline] + fn inner(&self) -> &ArcInner { + // SAFETY: While this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` if the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. + unsafe { self.ptr.as_ref() } + } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + // Drop the weak ref collectively held by all strong references when this + // variable goes out of scope. This ensures that the memory is deallocated + // even if the destructor of `T` panics. + // Take a reference to `self.alloc` instead of cloning because 1. it'll last long + // enough, and 2. you should be able to drop `Arc`s with unclonable allocators + let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + + // Destroy the data at this time, even though we must not free the box + // allocation itself (there might still be weak pointers lying around). + // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. + // ignore-tidy-undocumented-unsafe + unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; + } + + /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to + /// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let same_five = Arc::clone(&five); + /// let other_five = Arc::new(5); + /// + /// assert!(Arc::ptr_eq(&five, &same_five)); + /// assert!(!Arc::ptr_eq(&five, &other_five)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq "ptr::eq" + #[inline] + #[must_use] + #[stable(feature = "ptr_eq", since = "1.17.0")] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr()) + } +} + +impl Arc { + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> *mut ArcInner { + let layout = arcinner_layout_for_value_layout(value_layout); + + let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + + // ignore-tidy-undocumented-unsafe + unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) } + } + + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> Result<*mut ArcInner, AllocError> { + let layout = arcinner_layout_for_value_layout(value_layout); + + let ptr = allocate(layout)?; + + // ignore-tidy-undocumented-unsafe + let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }; + + Ok(inner) + } + + unsafe fn initialize_arcinner( + ptr: NonNull<[u8]>, + layout: Layout, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> *mut ArcInner { + let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); + // SAFETY: Upheld by caller. + debug_assert_eq!(unsafe { Layout::for_value_raw(inner) }, layout); + + // ignore-tidy-undocumented-unsafe + unsafe { + (&raw mut (*inner).strong).write(atomic::AtomicUsize::new(1)); + (&raw mut (*inner).weak).write(atomic::AtomicUsize::new(1)); + } + + inner + } +} + +impl Arc { + /// Allocates an `ArcInner` with sufficient space for an unsized inner value. + #[inline] + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut ArcInner { + // Allocate for the `ArcInner` using the given value. + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::allocate_for_layout( + Layout::for_value_raw(ptr), + |layout| alloc.allocate(layout), + |mem| mem.with_metadata_of(ptr as *const ArcInner), + ) + } + } + + #[cfg(not(no_global_oom_handling))] + fn from_box_in(src: Box) -> Arc { + // ignore-tidy-undocumented-unsafe + unsafe { + let value_size = size_of_val(&*src); + let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); + + // Copy value as bytes + ptr::copy_nonoverlapping( + (&raw const *src) as *const u8, + (&raw mut (*ptr).data) as *mut u8, + value_size, + ); + + // Free the allocation without dropping its contents + let (bptr, alloc) = Box::into_raw_with_allocator(src); + let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop, &alloc); + drop(src); + + Self::from_ptr_in(ptr, alloc) + } + } +} + +impl Arc<[T]> { + /// Allocates an `ArcInner<[T]>` with the given length. + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { + // ignore-tidy-undocumented-unsafe + unsafe { + Self::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate(layout), + |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[T]>, + ) + } + } + + /// Copy elements from slice into newly allocated `Arc<[T]>` + /// + /// Unsafe because the caller must either take ownership, bind `T: Copy` or + /// bind `T: TrivialClone`. + #[cfg(not(no_global_oom_handling))] + unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { + // ignore-tidy-undocumented-unsafe + unsafe { + let ptr = Self::allocate_for_slice(v.len()); + + ptr::copy_nonoverlapping(v.as_ptr(), (&raw mut (*ptr).data) as *mut T, v.len()); + + Self::from_ptr(ptr) + } + } + + /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + #[cfg(not(no_global_oom_handling))] + unsafe fn from_iter_exact(iter: impl Iterator, len: usize) -> Arc<[T]> { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new ArcInner will be dropped, then the memory freed. + struct Guard { + mem: NonNull, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl Drop for Guard { + fn drop(&mut self) { + // ignore-tidy-undocumented-unsafe + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Global.deallocate(self.mem, self.layout); + } + } + } + + // ignore-tidy-undocumented-unsafe + unsafe { + let ptr = Self::allocate_for_slice(len); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value_raw(ptr); + + // Pointer to first element + let elems = (&raw mut (*ptr).data) as *mut T; + + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new ArcInner. + mem::forget(guard); + + Self::from_ptr(ptr) + } + } +} + +impl Arc<[T], A> { + /// Allocates an `ArcInner<[T]>` with the given length. + #[inline] + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut ArcInner<[T]> { + // ignore-tidy-undocumented-unsafe + unsafe { + Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| alloc.allocate(layout), + |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[T]>, + ) + } + } +} + +/// Specialization trait used for `From<&[T]>`. +#[cfg(not(no_global_oom_handling))] +trait ArcFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +#[cfg(not(no_global_oom_handling))] +impl ArcFromSlice for Arc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + // ignore-tidy-undocumented-unsafe + unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl ArcFromSlice for Arc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + // SAFETY: `T` implements `TrivialClone`, so this is sound and equivalent + // to the above. + unsafe { Arc::copy_from_slice(v) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Arc { + /// Makes a clone of the `Arc` pointer. + /// + /// This creates another pointer to the same allocation, increasing the + /// strong reference count. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let _ = Arc::clone(&five); + /// ``` + #[inline] + fn clone(&self) -> Arc { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object. + // + // As explained in the [Boost documentation][1], Increasing the + // reference counter can always be done with memory_order_relaxed: New + // references to an object can only be formed from an existing + // reference, and passing an existing reference from one thread to + // another must already provide any required synchronization. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + let old_size = self.inner().strong.fetch_add(1, Relaxed); + + // However we need to guard against massive refcounts in case someone is `mem::forget`ing + // Arcs. If we don't do this the count can overflow and users will use-after free. This + // branch will never be taken in any realistic program. We abort because such a program is + // incredibly degenerate, and we don't care to support it. + // + // This check is not 100% water-proof: we error when the refcount grows beyond `isize::MAX`. + // But we do that check *after* having done the increment, so there is a chance here that + // the worst already happened and we actually do overflow the `usize` counter. However, that + // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment + // above and the `abort` below, which seems exceedingly unlikely. + // + // This is a global invariant, and also applies when using a compare-exchange loop to increment + // counters in other methods. + // Otherwise, the counter could be brought to an almost-overflow using a compare-exchange loop, + // and then overflow using a few `fetch_add`s. + if old_size > MAX_REFCOUNT { + abort(); + } + + // SAFETY: Pointer is valid & allocator corresponds to the one used to allocate it. + unsafe { Self::from_inner_in(self.ptr, self.alloc.clone()) } + } +} + +#[unstable(feature = "ergonomic_clones", issue = "132290")] +impl UseCloned for Arc {} + +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Arc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Arc { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.inner().data + } +} + +// The API of this pointer type enforces that if the `T` is pinned, then *all* +// clones of this `Arc` are wrapped as `Pin>`. Since an `&Arc` +// could be used to obtain an `Arc` that is not wrapped in `Pin` (and later +// used with `Arc::get_mut`), this means that this type treats `&Arc` as +// evidence that the `T` is not pinned. The implementations of various traits +// are written accordingly. Since this type is not fundamental, downstream +// crates cannot provide malicious implementations of any of the traits relevant +// for `Pin`. +#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] +unsafe impl PinSafePointer for Arc {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Arc {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Arc {} + +#[cfg(not(no_global_oom_handling))] +impl Arc { + /// Makes a mutable reference into the given `Arc`. + /// + /// If there are other `Arc` pointers to the same allocation, then `make_mut` will + /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also + /// referred to as clone-on-write. + /// + /// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`] + /// pointers, then the [`Weak`] pointers will be dissociated and the inner value will not + /// be cloned. + /// + /// See also [`get_mut`], which will fail rather than cloning the inner value + /// or dissociating [`Weak`] pointers. + /// + /// [`clone`]: Clone::clone + /// [`get_mut`]: Arc::get_mut + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(5); + /// + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = Arc::clone(&data); // Won't clone inner data + /// *Arc::make_mut(&mut data) += 1; // Clones inner data + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Now `data` and `other_data` point to different allocations. + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); + /// ``` + /// + /// [`Weak`] pointers will be dissociated: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(75); + /// let weak = Arc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Arc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn make_mut(this: &mut Self) -> &mut T { + let size_of_val = size_of_val::(&**this); + + // Note that we hold both a strong reference and a weak reference. + // Thus, releasing our strong reference only will not, by itself, cause + // the memory to be deallocated. + // + // Use Acquire to ensure that we see any writes to `weak` that happen + // before release writes (i.e., decrements) to `strong`. Since we hold a + // weak count, there's no chance the ArcInner itself could be + // deallocated. + if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { + // Another strong pointer exists, so we must clone. + *this = Arc::clone_from_ref_in(&**this, this.alloc.clone()); + } else if this.inner().weak.load(Relaxed) != 1 { + // Relaxed suffices in the above because this is fundamentally an + // optimization: we are always racing with weak pointers being + // dropped. Worst case, we end up allocated a new Arc unnecessarily. + + // We removed the last strong ref, but there are additional weak + // refs remaining. We'll move the contents to a new Arc, and + // invalidate the other weak refs. + + // Note that it is not possible for the read of `weak` to yield + // usize::MAX (i.e., locked), since the weak count can only be + // locked by a thread with a strong reference. + + // Guard against panics while using the allocator. + // If we unwind before the Arc is overwritten, we expose a strong + // count of 0, resulting in a UAF (#155746, #157203). + // Until the new Arc is written, the old Arc must remain valid + struct Guard<'a, T: ?Sized> { + inner: &'a ArcInner, + } + impl<'a, T: ?Sized> Drop for Guard<'a, T> { + fn drop(&mut self) { + self.inner.strong.store(1, Release); + } + } + let guard = Guard { inner: this.inner() }; + + // Can just steal the data, all that's left is Weaks + // Note that this can panic in two ways: + // - The allocation can fail + // - The allocator clone can fail + let mut in_progress: UniqueArcUninit = + UniqueArcUninit::new(&**this, this.alloc.clone()); + + // ignore-tidy-undocumented-unsafe + unsafe { + // Initialize `in_progress` with move of **this. + // We have to express this in terms of bytes because `T: ?Sized`; there is no + // operation that just copies a value based on its `size_of_val()`. + ptr::copy_nonoverlapping( + ptr::from_ref(&**this).cast::(), + in_progress.data_ptr().cast::(), + size_of_val, + ); + + // We are now safe from panics. + mem::forget(guard); + + // Materialize our own implicit weak pointer, so that it can clean + // up the ArcInner as needed. + // Make sure the allocator is not leaked when the Arc is overwritten. + // Only drop at the end of the scope to avoid panics. + let _weak = Weak { ptr: this.ptr, alloc: ptr::read(&this.alloc) }; + + ptr::write(this, in_progress.into_arc()); + } + } else { + // We were the sole reference of either kind; bump back up the + // strong ref count. + this.inner().strong.store(1, Release); + } + + // SAFETY: As with `get_mut()`, our reference was + // either unique to begin with, or became one upon cloning the contents. + unsafe { Self::get_mut_unchecked(this) } + } +} + +impl Arc { + /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the + /// clone. + /// + /// Assuming `arc_t` is of type `Arc`, this function is functionally equivalent to + /// `(*arc_t).clone()`, but will avoid cloning the inner value where possible. + /// + /// # Examples + /// + /// ``` + /// # use std::{ptr, sync::Arc}; + /// let inner = String::from("test"); + /// let ptr = inner.as_ptr(); + /// + /// let arc = Arc::new(inner); + /// let inner = Arc::unwrap_or_clone(arc); + /// // The inner value was not cloned + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// + /// let arc = Arc::new(inner); + /// let arc2 = arc.clone(); + /// let inner = Arc::unwrap_or_clone(arc); + /// // Because there were 2 references, we had to clone the inner value. + /// assert!(!ptr::eq(ptr, inner.as_ptr())); + /// // `arc2` is the last reference, so when we unwrap it we get back + /// // the original `String`. + /// let inner = Arc::unwrap_or_clone(arc2); + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// ``` + #[inline] + #[stable(feature = "arc_unwrap_or_clone", since = "1.76.0")] + pub fn unwrap_or_clone(this: Self) -> T { + Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) + } +} + +impl Arc { + /// Returns a mutable reference into the given `Arc`, if there are + /// no other `Arc` or [`Weak`] pointers to the same allocation. + /// + /// Returns [`None`] otherwise, because it is not safe to + /// mutate a shared value. + /// + /// See also [`make_mut`][make_mut], which will [`clone`][clone] + /// the inner value when there are other `Arc` pointers. + /// + /// [make_mut]: Arc::make_mut + /// [clone]: Clone::clone + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(3); + /// *Arc::get_mut(&mut x).unwrap() = 4; + /// assert_eq!(*x, 4); + /// + /// let _y = Arc::clone(&x); + /// assert!(Arc::get_mut(&mut x).is_none()); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if Self::is_unique(this) { + // SAFETY: We're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + unsafe { Some(Arc::get_mut_unchecked(this)) } + } else { + None + } + } + + /// Returns a mutable reference into the given `Arc`, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: Arc::get_mut + /// + /// # Safety + /// + /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then + /// they must not be dereferenced or have active borrows for the duration + /// of the returned borrow, and their inner type must be exactly the same as the + /// inner type of this Arc (including lifetimes). This is trivially the case if no + /// such pointers exist, for example immediately after `Arc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + /// Other `Arc` pointers to the same allocation must be to the same type. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::from("Hello, world!"); + /// let mut y: Arc<[u8]> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type is str, not [u8] + /// Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 + /// } + /// println!("{}", &*x); // Invalid UTF-8 in a str + /// ``` + /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc<&str> = Arc::new("Hello, world!"); + /// { + /// let s = String::from("Oh, no!"); + /// let mut y: Arc<&str> = x.clone(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type + /// // is &'long str, not &'short str + /// *Arc::get_mut_unchecked(&mut y) = &s; + /// } + /// } + /// println!("{}", &*x); // Use-after-free + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + // We are careful to *not* create a reference covering the "count" fields, as + // this would alias with concurrent access to the reference counts (e.g. by `Weak`). + // ignore-tidy-undocumented-unsafe + unsafe { &mut (*this.ptr.as_ptr()).data } + } + + /// Determine whether this is the unique reference to the underlying data. + /// + /// Returns `true` if there are no other `Arc` or [`Weak`] pointers to the same allocation; + /// returns `false` otherwise. + /// + /// If this function returns `true`, then is guaranteed to be safe to call [`get_mut_unchecked`] + /// on this `Arc`, so long as no clones occur in between. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_is_unique)] + /// + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// assert!(Arc::is_unique(&x)); + /// + /// let y = Arc::clone(&x); + /// assert!(!Arc::is_unique(&x)); + /// drop(y); + /// + /// // Weak references also count, because they could be upgraded at any time. + /// let z = Arc::downgrade(&x); + /// assert!(!Arc::is_unique(&x)); + /// ``` + /// + /// # Pointer invalidation + /// + /// This function will always return the same value as `Arc::get_mut(arc).is_some()`. However, + /// unlike that operation it does not produce any mutable references to the underlying data, + /// meaning no pointers to the data inside the `Arc` are invalidated by the call. Thus, the + /// following code is valid, even though it would be UB if it used `Arc::get_mut`: + /// + /// ``` + /// #![feature(arc_is_unique)] + /// + /// use std::sync::Arc; + /// + /// let arc = Arc::new(5); + /// let pointer: *const i32 = &*arc; + /// assert!(Arc::is_unique(&arc)); + /// assert_eq!(unsafe { *pointer }, 5); + /// ``` + /// + /// # Atomic orderings + /// + /// Concurrent drops to other `Arc` pointers to the same allocation will synchronize with this + /// call - that is, this call performs an `Acquire` operation on the underlying strong and weak + /// ref counts. This ensures that calling `get_mut_unchecked` is safe. + /// + /// Note that this operation requires locking the weak ref count, so concurrent calls to + /// `downgrade` may spin-loop for a short period of time. + /// + /// [`get_mut_unchecked`]: Self::get_mut_unchecked + #[inline] + #[unstable(feature = "arc_is_unique", issue = "138938")] + pub fn is_unique(this: &Self) -> bool { + // lock the weak pointer count if we appear to be the sole weak pointer + // holder. + // + // The acquire label here ensures a happens-before relationship with any + // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements + // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded + // weak ref was never dropped, the CAS here will fail so we do not care to synchronize. + if this.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { + // This needs to be an `Acquire` to synchronize with the decrement of the `strong` + // counter in `drop` -- the only access that happens when any but the last reference + // is being dropped. + let unique = this.inner().strong.load(Acquire) == 1; + + // The release write here synchronizes with a read in `downgrade`, + // effectively preventing the above read of `strong` from happening + // after the write. + this.inner().weak.store(1, Release); // release the lock + unique + } else { + false + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { + /// Drops the `Arc`. + /// + /// This will decrement the strong reference count. If the strong reference + /// count reaches zero then the only other references (if any) are + /// [`Weak`], so we `drop` the inner value. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let foo2 = Arc::clone(&foo); + /// + /// drop(foo); // Doesn't print anything + /// drop(foo2); // Prints "dropped!" + /// ``` + #[inline] + fn drop(&mut self) { + // Because `fetch_sub` is already atomic, we do not need to synchronize + // with other threads unless we are going to delete the object. This + // same logic applies to the below `fetch_sub` to the `weak` count. + if self.inner().strong.fetch_sub(1, Release) != 1 { + return; + } + + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // In particular, while the contents of an Arc are usually immutable, it's + // possible to have interior writes to something like a Mutex. Since a + // Mutex is not acquired when it is deleted, we can't rely on its + // synchronization logic to make writes in thread A visible to a destructor + // running in thread B. + // + // Also note that the Acquire fence here could probably be replaced with an + // Acquire load, which could improve performance in highly-contended + // situations. See [2]. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + // [2]: (https://github.com/rust-lang/rust/pull/41714) + acquire!(self.inner().strong); + + // Make sure we aren't trying to "drop" the shared static for empty slices + // used by Default::default. + debug_assert!( + !ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner), + "Arcs backed by a static should never reach a strong count of 0. \ + Likely decrement_strong_count or from_raw were called too many times.", + ); + + // ignore-tidy-undocumented-unsafe + unsafe { + self.drop_slow(); + } + } +} + +impl Arc { + /// Attempts to downcast the `Arc` to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// use std::sync::Arc; + /// + /// fn print_if_string(value: Arc) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Arc::new(my_string)); + /// print_if_string(Arc::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] + pub fn downcast(self) -> Result, Self> + where + T: Any + Send + Sync, + { + if (*self).is::() { + // SAFETY: Check ensures the typecast is okay. + unsafe { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + Ok(Arc::from_inner_in(ptr.cast(), alloc)) + } + } else { + Err(self) + } + } + + /// Downcasts the `Arc` to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Arc + where + T: Any + Send + Sync, + { + // SAFETY: Upheld by caller. + unsafe { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + Arc::from_inner_in(ptr.cast(), alloc) + } + } +} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] + #[must_use] + pub const fn new() -> Weak { + Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global } + } +} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory, technically in the provided + /// allocator. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// + /// use std::sync::Weak; + /// use std::alloc::System; + /// + /// let empty: Weak = Weak::new_in(System); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn new_in(alloc: A) -> Weak { + Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc } + } +} + +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a Atomic, + strong: &'a Atomic, +} + +impl Weak { + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference, and must point to a block of memory allocated by global allocator. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Arc::downgrade(&strong).into_raw(); + /// let raw_2 = Arc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`new`]: Weak::new + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + #[inline] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Upheld by caller. + unsafe { Weak::from_raw_in(ptr, Global) } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + ManuallyDrop::new(self).as_ptr() + } +} + +impl Weak { + /// Returns a reference to the underlying allocator. + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn allocator(&self) -> &A { + &self.alloc + } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::ptr; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_ptr())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to + /// // undefined behavior. + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// ``` + /// + /// [`null`]: core::ptr::null "ptr::null" + #[must_use] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn as_ptr(&self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); + + if is_dangling(ptr) { + // If the pointer is dangling, we return the sentinel directly. This cannot be + // a valid payload address, as the payload is at least as aligned as ArcInner (usize). + ptr as *const T + } else { + // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. + // The payload may be dropped at this point, and we have to maintain provenance, + // so use raw pointer manipulation. + unsafe { &raw mut (*ptr).data } + } + } + + /// Consumes the `Weak`, returning the wrapped pointer and allocator. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw_in`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_ext)] + /// use std::sync::{Arc, Weak}; + /// use std::alloc::System; + /// + /// let strong = Arc::new_in("hello".to_owned(), System); + /// let weak = Arc::downgrade(&strong); + /// let (raw, alloc) = weak.into_raw_with_allocator(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw_in(raw, alloc) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw_in`]: Weak::from_raw_in + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub fn into_raw_with_allocator(self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(self); + let result = this.as_ptr(); + // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + (result, alloc) + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak` in the provided + /// allocator. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference, and must point to a block of memory allocated by `alloc`. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Arc::downgrade(&strong).into_raw(); + /// let raw_2 = Arc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`new`]: Weak::new + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + #[inline] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] + pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + // See Weak::as_ptr for context on how the input pointer is derived. + + let ptr = if is_dangling(ptr) { + // This is a dangling Weak. + ptr as *mut ArcInner + } else { + // Otherwise, we're guaranteed the pointer came from a nondangling Weak. + // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. + let offset = unsafe { data_offset(ptr) }; + // Thus, we reverse the offset to get the whole ArcInner. + // SAFETY: the pointer originated from a Weak, so this offset is safe. + unsafe { ptr.byte_sub(offset) as *mut ArcInner } + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) }, alloc } + } +} + +impl Weak { + /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying + /// dropping of the inner value if successful. + /// + /// Returns [`None`] in the following cases: + /// + /// 1. The inner value has since been dropped or moved out. + /// + /// 2. This `Weak` does not point to an allocation. + /// + /// 3. The owning reference this `Weak` is associated with is either not fully-constructed or does not allow an upgrade. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// + /// let strong_five: Option> = weak_five.upgrade(); + /// assert!(strong_five.is_some()); + /// + /// // Destroy all strong pointers. + /// drop(strong_five); + /// drop(five); + /// + /// assert!(weak_five.upgrade().is_none()); + /// ``` + #[must_use = "this returns a new `Arc`, \ + without modifying the original weak pointer"] + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn upgrade(&self) -> Option> + where + A: AllocatorClone, + { + #[inline] + fn checked_increment(n: usize) -> Option { + // Any write of 0 we can observe leaves the field in permanently zero state. + if n == 0 { + return None; + } + // See comments in `Arc::clone` for why we do this (for `mem::forget`). + if n > MAX_REFCOUNT { + panic_arc_overflow(); + } + Some(n + 1) + } + + // We use a CAS loop to increment the strong count instead of a + // fetch_add as this function should never take the reference count + // from zero to one. + // + // Relaxed is fine for the failure case because we don't have any expectations about the new state. + // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner + // value can be initialized after `Weak` references have already been created. In that case, we + // expect to observe the fully initialized value. + if self.inner()?.strong.try_update(Acquire, Relaxed, checked_increment).is_ok() { + // SAFETY: pointer is not null, verified in checked_increment + unsafe { Some(Arc::from_inner_in(self.ptr, self.alloc.clone())) } + } else { + None + } + } + + /// Gets the number of strong (`Arc`) pointers pointing to this allocation. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + #[must_use] + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { inner.strong.load(Relaxed) } else { 0 } + } + + /// Gets an approximation of the number of `Weak` pointers pointing to this + /// allocation. + /// + /// If `self` was created using [`Weak::new`], or if there are no remaining + /// strong pointers, this will return 0. + /// + /// # Accuracy + /// + /// Due to implementation details, the returned value can be off by 1 in + /// either direction when other threads are manipulating any `Arc`s or + /// `Weak`s pointing to the same allocation. + #[must_use] + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { + if let Some(inner) = self.inner() { + let weak = inner.weak.load(Acquire); + let strong = inner.strong.load(Relaxed); + if strong == 0 { + 0 + } else { + // Since we observed that there was at least one strong pointer + // after reading the weak count, we know that the implicit weak + // reference (present whenever any strong references are alive) + // was still around when we observed the weak count, and can + // therefore safely subtract it. + weak - 1 + } + } else { + 0 + } + } + + /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, + /// (i.e., when this `Weak` was created by `Weak::new`). + #[inline] + fn inner(&self) -> Option> { + let ptr = self.ptr.as_ptr(); + if is_dangling(ptr) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Arc` + // is dropped, the data field will be dropped in-place). + // ignore-tidy-undocumented-unsafe + Some(unsafe { WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } }) + } + } + + /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if + /// both don't point to any allocation (because they were created with `Weak::new()`). However, + /// this function ignores the metadata of `dyn Trait` pointers. + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let first_rc = Arc::new(5); + /// let first = Arc::downgrade(&first_rc); + /// let second = Arc::downgrade(&first_rc); + /// + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Arc::new(5); + /// let third = Arc::downgrade(&third_rc); + /// + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Arc::new(()); + /// let third = Arc::downgrade(&third_rc); + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq "ptr::eq" + #[inline] + #[must_use] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] + pub fn ptr_eq(&self, other: &Self) -> bool { + ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr()) + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl Clone for Weak { + /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let weak_five = Arc::downgrade(&Arc::new(5)); + /// + /// let _ = Weak::clone(&weak_five); + /// ``` + #[inline] + fn clone(&self) -> Weak { + if let Some(inner) = self.inner() { + // See comments in Arc::clone() for why this is relaxed. This can use a + // fetch_add (ignoring the lock) because the weak count is only locked + // where are *no other* weak pointers in existence. (So we can't be + // running this code in that case). + let old_size = inner.weak.fetch_add(1, Relaxed); + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + abort(); + } + } + + Weak { ptr: self.ptr, alloc: self.alloc.clone() } + } +} + +#[unstable(feature = "ergonomic_clones", issue = "132290")] +impl UseCloned for Weak {} + +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + /// Constructs a new `Weak`, without allocating memory. + /// Calling [`upgrade`] on the return value always + /// gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Default::default(); + /// assert!(empty.upgrade().is_none()); + /// ``` + fn default() -> Weak { + Weak::new() + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak { + /// Drops the `Weak` pointer. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let weak_foo = Arc::downgrade(&foo); + /// let other_weak_foo = Weak::clone(&weak_foo); + /// + /// drop(weak_foo); // Doesn't print anything + /// drop(foo); // Prints "dropped!" + /// + /// assert!(other_weak_foo.upgrade().is_none()); + /// ``` + fn drop(&mut self) { + // If we find out that we were the last weak pointer, then its time to + // deallocate the data entirely. See the discussion in Arc::drop() about + // the memory orderings + // + // It's not necessary to check for the locked state here, because the + // weak count can only be locked if there was precisely one weak ref, + // meaning that drop could only subsequently run ON that remaining weak + // ref, which can only happen after the lock is released. + let inner = if let Some(inner) = self.inner() { inner } else { return }; + + if inner.weak.fetch_sub(1, Release) == 1 { + acquire!(inner.weak); + + // Make sure we aren't trying to "deallocate" the shared static for empty slices + // used by Default::default. + debug_assert!( + !ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner), + "Arc/Weaks backed by a static should never be deallocated. \ + Likely decrement_strong_count or from_raw were called too many times.", + ); + + // ignore-tidy-undocumented-unsafe + unsafe { + self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())) + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +trait ArcEqIdent { + fn eq(&self, other: &Arc) -> bool; + fn ne(&self, other: &Arc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + default fn eq(&self, other: &Arc) -> bool { + **self == **other + } + #[inline] + default fn ne(&self, other: &Arc) -> bool { + **self != **other + } +} + +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Arc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to +/// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + fn eq(&self, other: &Arc) -> bool { + ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) || **self == **other + } + + #[inline] + fn ne(&self, other: &Arc) -> bool { + !ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Arc { + /// Equality for two `Arc`s. + /// + /// Two `Arc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same allocation are always equal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five == Arc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Arc) -> bool { + ArcEqIdent::eq(self, other) + } + + /// Inequality for two `Arc`s. + /// + /// Two `Arc`s are not equal if their inner values are not equal. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same value are always equal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five != Arc::new(6)); + /// ``` + #[inline] + fn ne(&self, other: &Arc) -> bool { + ArcEqIdent::ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Arc { + /// Partial comparison for two `Arc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6))); + /// ``` + fn partial_cmp(&self, other: &Arc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `Arc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five < Arc::new(6)); + /// ``` + fn lt(&self, other: &Arc) -> bool { + *(*self) < *(*other) + } + + /// 'Less than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five <= Arc::new(5)); + /// ``` + fn le(&self, other: &Arc) -> bool { + *(*self) <= *(*other) + } + + /// Greater-than comparison for two `Arc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five > Arc::new(4)); + /// ``` + fn gt(&self, other: &Arc) -> bool { + *(*self) > *(*other) + } + + /// 'Greater than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five >= Arc::new(5)); + /// ``` + fn ge(&self, other: &Arc) -> bool { + *(*self) >= *(*other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Arc { + /// Comparison for two `Arc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6))); + /// ``` + fn cmp(&self, other: &Arc) -> Ordering { + (**self).cmp(&**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Arc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&raw const **self), f) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Arc { + /// Creates a new `Arc`, with the `Default` value for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc = Default::default(); + /// assert_eq!(*x, 0); + /// ``` + fn default() -> Arc { + // ignore-tidy-undocumented-unsafe + unsafe { + Self::from_inner(Box::into_non_null(Box::write( + Box::new_uninit(), + ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: T::default(), + }, + ))) + } + } +} + +/// Struct to hold the static `ArcInner` used for empty `Arc` as +/// returned by `Default::default`. +/// +/// Layout notes: +/// * `repr(align(16))` so we can use it for `[T]` with `align_of::() <= 16`. +/// * `repr(C)` so `inner` is at offset 0 (and thus guaranteed to actually be aligned to 16). +/// * `[u8; 1]` (to be initialized with 0) so it can be used for `Arc`. +#[repr(C, align(16))] +struct SliceArcInnerForStatic { + inner: ArcInner<[u8; 1]>, +} +#[cfg(not(no_global_oom_handling))] +const MAX_STATIC_INNER_SLICE_ALIGNMENT: usize = 16; + +static STATIC_INNER_SLICE: SliceArcInnerForStatic = SliceArcInnerForStatic { + inner: ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: [0], + }, +}; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Arc { + /// Creates an empty str inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + let arc: Arc<[u8]> = Default::default(); + debug_assert!(core::str::from_utf8(&arc).is_ok()); + let (ptr, alloc) = Arc::into_inner_with_allocator(arc); + // ignore-tidy-undocumented-unsafe + unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner, alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Arc { + /// Creates an empty CStr inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + use core::ffi::CStr; + let inner: NonNull> = NonNull::from(&STATIC_INNER_SLICE.inner); + let inner: NonNull> = + NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = + // ignore-tidy-undocumented-unsafe + unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + (*this).clone() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Arc<[T]> { + /// Creates an empty `[T]` inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + if align_of::() <= MAX_STATIC_INNER_SLICE_ALIGNMENT { + // We take a reference to the whole struct instead of the ArcInner<[u8; 1]> inside it so + // we don't shrink the range of bytes the ptr is allowed to access under Stacked Borrows. + // (Miri complains on 32-bit targets with Arc<[Align16]> otherwise.) + // (Note that NonNull::from(&STATIC_INNER_SLICE.inner) is fine under Tree Borrows.) + let inner: NonNull = NonNull::from(&STATIC_INNER_SLICE); + let inner: NonNull> = inner.cast(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = + // ignore-tidy-undocumented-unsafe + unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + return (*this).clone(); + } + + // If T's alignment is too large for the static, make a new unique allocation. + let arr: [T; 0] = []; + Arc::from(arr) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "pin_default_impls", since = "1.91.0")] +impl Default for Pin> +where + T: ?Sized, + Arc: Default, +{ + #[inline] + fn default() -> Self { + // SAFETY: We own and create the pinned pointer. + unsafe { Pin::new_unchecked(Arc::::default()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Arc { + fn hash(&self, state: &mut H) { + (**self).hash(state) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Arc { + /// Converts a `T` into an `Arc` + /// + /// The conversion moves the value into a + /// newly allocated `Arc`. It is equivalent to + /// calling `Arc::new(t)`. + /// + /// # Example + /// ```rust + /// # use std::sync::Arc; + /// let x = 5; + /// let arc = Arc::new(5); + /// + /// assert_eq!(Arc::from(x), arc); + /// ``` + fn from(t: T) -> Self { + Arc::new(t) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "1.74.0")] +impl From<[T; N]> for Arc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Arc`. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Arc<[T]> { + Arc::<[T; N]>::from(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&[T]> for Arc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: &[i32] = &[1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &[T]) -> Arc<[T]> { + >::from_slice(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut [T]> for Arc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let mut original = [1, 2, 3]; + /// let original: &mut [i32] = &mut original; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &mut [T]) -> Arc<[T]> { + Arc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&str> for Arc { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let shared: Arc = Arc::from("eggplant"); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: &str) -> Arc { + let arc = Arc::<[u8]>::from(v.as_bytes()); + // ignore-tidy-undocumented-unsafe + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const str) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut str> for Arc { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let mut original = String::from("eggplant"); + /// let original: &mut str = &mut original; + /// let shared: Arc = Arc::from(original); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: &mut str) -> Arc { + Arc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From for Arc { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: String = "eggplant".to_owned(); + /// let shared: Arc = Arc::from(unique); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: String) -> Arc { + Arc::from(&v[..]) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Arc { + /// Move a boxed object to a new, reference-counted allocation. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: Box = Box::from("eggplant"); + /// let shared: Arc = Arc::from(unique); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: Box) -> Arc { + Arc::from_box_in(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Arc<[T], A> { + /// Allocates a reference-counted slice and moves `v`'s items into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: Vec = vec![1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(unique); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: Vec) -> Arc<[T], A> { + // ignore-tidy-undocumented-unsafe + unsafe { + let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_allocator(); + + let rc_ptr = Self::allocate_for_slice_in(len, &alloc); + ptr::copy_nonoverlapping(vec_ptr, (&raw mut (*rc_ptr).data) as *mut T, len); + + // Create a `Vec` with length 0, to deallocate the buffer + // without dropping its contents or the allocator + let _ = Vec::from_raw_parts_in(vec_ptr, 0, cap, &alloc); + + Self::from_ptr_in(rc_ptr, alloc) + } + } +} + +#[stable(feature = "shared_from_cow", since = "1.45.0")] +impl<'a, B> From> for Arc +where + B: ToOwned + ?Sized, + Arc: From<&'a B> + From, +{ + /// Creates an atomically reference-counted pointer from a clone-on-write + /// pointer by copying its content. + /// + /// # Example + /// + /// ```rust + /// # use std::sync::Arc; + /// # use std::borrow::Cow; + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); + /// let shared: Arc = Arc::from(cow); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(cow: Cow<'a, B>) -> Arc { + match cow { + Cow::Borrowed(s) => Arc::from(s), + Cow::Owned(s) => Arc::from(s), + } + } +} + +#[stable(feature = "shared_from_str", since = "1.62.0")] +impl From> for Arc<[u8]> { + /// Converts an atomically reference-counted string slice into a byte slice. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let string: Arc = Arc::from("eggplant"); + /// let bytes: Arc<[u8]> = Arc::from(string); + /// assert_eq!("eggplant".as_bytes(), bytes.as_ref()); + /// ``` + #[inline] + fn from(rc: Arc) -> Self { + // SAFETY: `str` has the same layout as `[u8]`. + unsafe { Arc::from_raw(Arc::into_raw(rc) as *const [u8]) } + } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Arc<[T; N], A> { + type Error = Arc<[T], A>; + + fn try_from(boxed_slice: Arc<[T], A>) -> Result { + if boxed_slice.len() == N { + let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice); + // ignore-tidy-undocumented-unsafe + Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) + } else { + Err(boxed_slice) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl FromIterator for Arc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Arc<[T]>` is done by first + /// collecting into a `Vec`. That is, when writing the following: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Arc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec` + /// and then it will allocate once for turning the `Vec` into the `Arc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Arc<[T]>`. For example: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::>()); + /// ``` + fn from_iter>(iter: I) -> Self { + ToArcSlice::to_arc_slice(iter.into_iter()) + } +} + +#[cfg(not(no_global_oom_handling))] +/// Specialization trait used for collecting into `Arc<[T]>`. +trait ToArcSlice: Iterator + Sized { + fn to_arc_slice(self) -> Arc<[T]>; +} + +#[cfg(not(no_global_oom_handling))] +impl> ToArcSlice for I { + default fn to_arc_slice(self) -> Arc<[T]> { + self.collect::>().into() + } +} + +#[cfg(not(no_global_oom_handling))] +impl> ToArcSlice for I { + fn to_arc_slice(self) -> Arc<[T]> { + // This is the case for a `TrustedLen` iterator. + let (low, high) = self.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, + high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + + // SAFETY: We need to ensure that the iterator has an exact length and we have. + unsafe { Arc::from_iter_exact(self, low) } + } else { + // TrustedLen contract guarantees that `upper_bound == None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl borrow::Borrow for Arc { + fn borrow(&self) -> &T { + self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Arc { + fn as_ref(&self) -> &T { + self + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Arc {} + +/// Gets the offset within an `ArcInner` for the payload behind a pointer. +/// +/// # Safety +/// +/// The pointer must point to (and have valid metadata for) a previously +/// valid instance of T, but the T is allowed to be dropped. +unsafe fn data_offset(ptr: *const T) -> usize { + // Align the unsized value to the end of the ArcInner. + // Because ArcInner is repr(C), it will always be the last field in memory. + // SAFETY: since the only unsized types possible are slices, trait objects, + // and extern types, the input safety requirement is currently enough to + // satisfy the requirements of Alignment::of_val_raw; this is an implementation + // detail of the language that must not be relied upon outside of std. + unsafe { data_offset_alignment(Alignment::of_val_raw(ptr)) } +} + +#[inline] +fn data_offset_alignment(alignment: Alignment) -> usize { + let layout = Layout::new::>(); + layout.size() + layout.padding_needed_for(alignment) +} + +/// A unique owning pointer to an [`ArcInner`] **that does not imply the contents are initialized,** +/// but will deallocate it (without dropping the value) when dropped. +/// +/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic. +struct UniqueArcUninit { + ptr: NonNull>, + layout_for_value: Layout, + alloc: Option, +} + +impl UniqueArcUninit { + /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it. + #[cfg(not(no_global_oom_handling))] + fn new(for_value: &T, alloc: A) -> UniqueArcUninit { + let layout = Layout::for_value(for_value); + // ignore-tidy-undocumented-unsafe + let ptr = unsafe { + Arc::allocate_for_layout( + layout, + |layout_for_arcinner| alloc.allocate(layout_for_arcinner), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner), + ) + }; + Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } + } + + /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it, + /// returning an error if allocation fails. + fn try_new(for_value: &T, alloc: A) -> Result, AllocError> { + let layout = Layout::for_value(for_value); + // ignore-tidy-undocumented-unsafe + let ptr = unsafe { + Arc::try_allocate_for_layout( + layout, + |layout_for_arcinner| alloc.allocate(layout_for_arcinner), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner), + )? + }; + Ok(Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }) + } + + /// Returns the pointer to be written into to initialize the [`Arc`]. + fn data_ptr(&mut self) -> *mut T { + let offset = data_offset_alignment(self.layout_for_value.alignment()); + // ignore-tidy-undocumented-unsafe + unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } + } + + /// Upgrade this into a normal [`Arc`]. + /// + /// # Safety + /// + /// The data must have been initialized (by writing to [`Self::data_ptr()`]). + unsafe fn into_arc(self) -> Arc { + let mut this = ManuallyDrop::new(self); + let ptr = this.ptr.as_ptr(); + let alloc = this.alloc.take().unwrap(); + + // SAFETY: The pointer is valid as per `UniqueArcUninit::new`, and the caller is responsible + // for having initialized the data. + unsafe { Arc::from_ptr_in(ptr, alloc) } + } +} + +impl Drop for UniqueArcUninit { + fn drop(&mut self) { + // SAFETY: + // * new() produced a pointer safe to deallocate. + // * We own the pointer unless into_arc() was called, which forgets us. + unsafe { + self.alloc.take().unwrap().deallocate( + self.ptr.cast(), + arcinner_layout_for_value_layout(self.layout_for_value), + ); + } + } +} + +#[stable(feature = "arc_error", since = "1.52.0")] +impl core::error::Error for Arc { + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn core::error::Error> { + core::error::Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + core::error::Error::source(&**self) + } + + fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) { + core::error::Error::provide(&**self, req); + } +} + +/// A uniquely owned [`Arc`]. +/// +/// This represents an `Arc` that is known to be uniquely owned -- that is, have exactly one strong +/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong +/// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`. +/// +/// Because it is uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common +/// use case is to have an object be mutable during its initialization phase but then have it become +/// immutable and converted to a normal `Arc`. +/// +/// This can be used as a flexible way to create cyclic data structures, as in the example below. +/// +/// ``` +/// #![feature(unique_rc_arc)] +/// use std::sync::{Arc, Weak, UniqueArc}; +/// +/// struct Gadget { +/// me: Weak, +/// } +/// +/// fn create_gadget() -> Option> { +/// let mut rc = UniqueArc::new(Gadget { +/// me: Weak::new(), +/// }); +/// rc.me = UniqueArc::downgrade(&rc); +/// Some(UniqueArc::into_arc(rc)) +/// } +/// +/// create_gadget().unwrap(); +/// ``` +/// +/// An advantage of using `UniqueArc` over [`Arc::new_cyclic`] to build cyclic data structures is that +/// [`Arc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the +/// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data, +/// including fallible or async constructors. +#[unstable(feature = "unique_rc_arc", issue = "112566")] +pub struct UniqueArc< + T: ?Sized, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, +> { + ptr: NonNull>, + // Define the ownership of `ArcInner` for drop-check + _marker: PhantomData>, + // Invariance is necessary for soundness: once other `Weak` + // references exist, we already have a form of shared mutability! + _marker2: PhantomData<*mut T>, + alloc: A, +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl Send for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl Sync for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +// #[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> + for UniqueArc +{ +} + +//#[unstable(feature = "unique_rc_arc", issue = "112566")] +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl fmt::Display for UniqueArc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl fmt::Debug for UniqueArc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl fmt::Pointer for UniqueArc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&raw const **self), f) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl borrow::Borrow for UniqueArc { + fn borrow(&self) -> &T { + self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl borrow::BorrowMut for UniqueArc { + fn borrow_mut(&mut self) -> &mut T { + self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl AsRef for UniqueArc { + fn as_ref(&self) -> &T { + self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl AsMut for UniqueArc { + fn as_mut(&mut self) -> &mut T { + self + } +} + +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl From for UniqueArc { + #[inline(always)] + fn from(value: T) -> Self { + Self::new(value) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Unpin for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl PartialEq for UniqueArc { + /// Equality for two `UniqueArc`s. + /// + /// Two `UniqueArc`s are equal if their inner values are equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five == UniqueArc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl PartialOrd for UniqueArc { + /// Partial comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// use std::cmp::Ordering; + /// + /// let five = UniqueArc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6))); + /// ``` + #[inline(always)] + fn partial_cmp(&self, other: &UniqueArc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five < UniqueArc::new(6)); + /// ``` + #[inline(always)] + fn lt(&self, other: &UniqueArc) -> bool { + **self < **other + } + + /// 'Less than or equal to' comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five <= UniqueArc::new(5)); + /// ``` + #[inline(always)] + fn le(&self, other: &UniqueArc) -> bool { + **self <= **other + } + + /// Greater-than comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five > UniqueArc::new(4)); + /// ``` + #[inline(always)] + fn gt(&self, other: &UniqueArc) -> bool { + **self > **other + } + + /// 'Greater than or equal to' comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five >= UniqueArc::new(5)); + /// ``` + #[inline(always)] + fn ge(&self, other: &UniqueArc) -> bool { + **self >= **other + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Ord for UniqueArc { + /// Comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// use std::cmp::Ordering; + /// + /// let five = UniqueArc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6))); + /// ``` + #[inline] + fn cmp(&self, other: &UniqueArc) -> Ordering { + (**self).cmp(&**other) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Eq for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Hash for UniqueArc { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +impl UniqueArc { + /// Creates a new `UniqueArc`. + /// + /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading + /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`]. + /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will + /// point to the new [`Arc`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn new(value: T) -> Self { + Self::new_in(value, Global) + } + + /// Like [`new`](Self::new), but returns an error if the allocation + /// fails, instead of calling [`handle_alloc_error`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn try_new(value: T) -> Result { + Self::try_new_in(value, Global) + } +} + +impl UniqueArc { + /// Creates a new `UniqueArc` in the provided allocator. + /// + /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading + /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`]. + /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will + /// point to the new [`Arc`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "163177")] + #[must_use] + pub fn new_in(data: T, alloc: A) -> Self { + let (ptr, alloc) = Box::into_non_null_with_allocator(Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + // keep one weak reference so if all the weak pointers that are created are dropped + // the UniqueArc still stays valid. + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + )); + Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc } + } + + /// Like [`new_in`](Self::new_in), but returns an error if the allocation + /// fails, instead of calling [`handle_alloc_error`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "163177")] + pub fn try_new_in(data: T, alloc: A) -> Result { + let (ptr, alloc) = Box::into_non_null_with_allocator(Box::try_new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + // keep one weak reference so if all the weak pointers that are created are dropped + // the UniqueArc still stays valid. + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + )?); + Ok(Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc }) + } + + /// Consumes the `UniqueArc`, returning its wrapped value and allocator. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "163177")] + #[must_use] + pub fn unwrap_with_allocator(this: Self) -> (T, A) { + let inner_ptr = this.ptr; + let (data_ptr, alloc) = Self::into_raw_with_allocator(this); + + // SAFETY: Conceptually moves out of the `UniqueRc`. + // We do not use the data inside ever again. + let val = unsafe { data_ptr.read() }; + + // Drop the strong-weak ref + drop(Weak { ptr: inner_ptr, alloc: &alloc }); + + (val, alloc) + } + + /// Consumes the `UniqueArc`, returning its wrapped value. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn unwrap(this: Self) -> T { + Self::unwrap_with_allocator(this).0 + } + + /// Maps the value in a `UniqueArc`, reusing the allocation if possible. + /// + /// `f` is called on a reference to the value in the `UniqueArc`, and the result is returned, + /// also in a `UniqueArc`. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `UniqueArc::map(u, f)` instead of `u.map(f)`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// + /// use std::sync::UniqueArc; + /// + /// let r = UniqueArc::new(7); + /// let new = UniqueArc::map(r, |i| i + 7); + /// assert_eq!(*new, 14); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn map(this: Self, f: impl FnOnce(T) -> U) -> UniqueArc { + if size_of::() == size_of::() + && align_of::() == align_of::() + && UniqueArc::weak_count(&this) == 0 + { + // ignore-tidy-undocumented-unsafe + unsafe { + let (ptr, alloc) = UniqueArc::into_raw_with_allocator(this); + let value = ptr.read(); + let allocation = + UniqueArc::from_raw_with_allocator(ptr.cast::>(), alloc); + + UniqueArc::write(allocation, f(value)) + } + } else { + let (val, alloc) = UniqueArc::unwrap_with_allocator(this); + UniqueArc::new_in(f(val), alloc) + } + } + + /// Attempts to map the value in a `UniqueArc`, reusing the allocation if possible. + /// + /// `f` is called on a reference to the value in the `UniqueArc`, and if the operation succeeds, + /// the result is returned, also in a `UniqueArc`. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `UniqueArc::try_map(u, f)` instead of `u.try_map(f)`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// ``` + /// #![feature(smart_pointer_try_map)] + /// #![feature(unique_rc_arc)] + /// + /// use std::sync::UniqueArc; + /// + /// let b = UniqueArc::new(7); + /// let new = UniqueArc::try_map(b, u32::try_from).unwrap(); + /// assert_eq!(*new, 7); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "smart_pointer_try_map", issue = "144419")] + pub fn try_map( + this: Self, + f: impl FnOnce(T) -> R, + ) -> >>::TryType + where + R: Try, + R::Residual: Residual>, + { + if size_of::() == size_of::() + && align_of::() == align_of::() + && UniqueArc::weak_count(&this) == 0 + { + // ignore-tidy-undocumented-unsafe + unsafe { + let (ptr, alloc) = UniqueArc::into_raw_with_allocator(this); + let value = ptr.read(); + let allocation = UniqueArc::from_raw_with_allocator( + ptr.cast::>(), + alloc, + ); + + try { UniqueArc::write(allocation, f(value)?) } + } + } else { + let (val, alloc) = UniqueArc::unwrap_with_allocator(this); + try { UniqueArc::new_in(f(val)?, alloc) } + } + } +} + +impl UniqueArc { + #[cfg(not(no_global_oom_handling))] + unsafe fn from_raw_with_allocator(ptr: *const T, alloc: A) -> Self { + // SAFETY: Upheld by caller. + let offset = unsafe { data_offset(ptr) }; + + // Reverse the offset to find the original ArcInner. + // SAFETY: Upheld by caller. + let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut ArcInner }; + + Self { + // SAFETY: Upheld by caller. + ptr: unsafe { NonNull::new_unchecked(rc_ptr) }, + _marker: PhantomData, + _marker2: PhantomData, + alloc, + } + } + + fn into_raw_with_allocator(this: Self) -> (*const T, A) { + let this = ManuallyDrop::new(this); + // SAFETY: The copy of the allocator stored in `this` is forgotten + (Self::as_ptr(&*this), unsafe { ptr::read(&this.alloc) }) + } + + /// Converts the `UniqueArc` into a regular [`Arc`]. + /// + /// This consumes the `UniqueArc` and returns a regular [`Arc`] that contains the `value` that + /// is passed to `into_arc`. + /// + /// Any weak references created before this method is called can now be upgraded to strong + /// references. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn into_arc(this: Self) -> Arc { + let this = ManuallyDrop::new(this); + + // Move the allocator out. + // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in + // a `ManuallyDrop`. + let alloc: A = unsafe { ptr::read(&this.alloc) }; + + // SAFETY: This pointer was allocated at creation time so we know it is valid. + unsafe { + // Convert our weak reference into a strong reference + (*this.ptr.as_ptr()).strong.store(1, Release); + Arc::from_inner_in(this.ptr, alloc) + } + } + + #[cfg(not(no_global_oom_handling))] + fn weak_count(this: &Self) -> usize { + this.inner().weak.load(Acquire) - 1 + } + + #[cfg(not(no_global_oom_handling))] + fn inner(&self) -> &ArcInner { + // SAFETY: while this UniqueArc is alive we're guaranteed that the inner pointer is valid. + unsafe { self.ptr.as_ref() } + } + + fn as_ptr(this: &Self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); + + // SAFETY: This cannot go through Deref::deref or UniqueArc::inner because + // this is required to retain raw/mut provenance such that e.g. `get_mut` can + // write through the pointer after the Rc is recovered through `from_raw`. + unsafe { &raw mut (*ptr).data } + } + + #[inline] + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); + // SAFETY: Pointer is valid for reads and only read once. + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + + #[inline] + unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { + Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc } + } +} + +impl UniqueArc { + /// Creates a new weak reference to the `UniqueArc`. + /// + /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted + /// to a [`Arc`] using [`UniqueArc::into_arc`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn downgrade(this: &Self) -> Weak { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object or converting the object to a normal `Arc`. + // + // Note that we don't need to test if the weak counter is locked because there + // are no such operations like `Arc::get_mut` or `Arc::make_mut` that will lock + // the weak counter. + // + // SAFETY: This pointer was allocated at creation time so we know it is valid. + let old_size = unsafe { (*this.ptr.as_ptr()).weak.fetch_add(1, Relaxed) }; + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + abort(); + } + + Weak { ptr: this.ptr, alloc: this.alloc.clone() } + } +} + +impl UniqueArc, A> { + /// Writes the value and converts to `UniqueArc`. + /// + /// This method converts similarly to [`assume_init`](Self::assume_init) but + /// writes `value` into it before conversion, thus guaranteeing safety. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn write(mut this: Self, value: T) -> UniqueArc { + // SAFETY: Writing initialises the wrapped value. + unsafe { + this.write(value); + this.assume_init() + } + } + + /// Converts to `UniqueArc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub unsafe fn assume_init(self) -> UniqueArc { + let (ptr, alloc) = UniqueArc::into_inner_with_allocator(self); + // SAFETY: Upheld by caller. + unsafe { UniqueArc::from_inner_in(ptr.cast(), alloc) } + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Deref for UniqueArc { + type Target = T; + + fn deref(&self) -> &T { + // SAFETY: This pointer was allocated at creation time so we know it is valid. + unsafe { &self.ptr.as_ref().data } + } +} + +// #[unstable(feature = "unique_rc_arc", issue = "112566")] +#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] +unsafe impl PinSafePointer for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl DerefMut for UniqueArc { + fn deref_mut(&mut self) -> &mut T { + // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we + // have unique ownership and therefore it's safe to make a mutable reference because + // `UniqueArc` owns the only strong reference to itself. + // We also need to be careful to only create a mutable reference to the `data` field, + // as a mutable reference to the entire `ArcInner` would assert uniqueness over the + // ref count fields too, invalidating any attempt by `Weak`s to access the ref count. + unsafe { &mut (*self.ptr.as_ptr()).data } + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +// #[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { + fn drop(&mut self) { + // See `Arc::drop_slow` which drops an `Arc` with a strong count of 0. + // SAFETY: This pointer was allocated at creation time so we know it is valid. + let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + + // ignore-tidy-undocumented-unsafe + unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; + } +} + +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +unsafe impl Allocator for Arc { + #[inline] + fn allocate(&self, layout: Layout) -> Result, AllocError> { + (**self).allocate(layout) + } + + #[inline] + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + (**self).allocate_zeroed(layout) + } + + #[inline] + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).deallocate(ptr, layout) } + } + + #[inline] + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow(ptr, old_layout, new_layout) } + } + + #[inline] + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) } + } + + #[inline] + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).shrink(ptr, old_layout, new_layout) } + } +} + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +unsafe impl AllocatorClone for Arc {} diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rcs/rc.rs similarity index 100% rename from library/alloc/src/rc.rs rename to library/alloc/src/rcs/rc.rs diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e412cee62d8f6..afb1848d21a24 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -8,5207 +8,7 @@ //! loads and stores of pointers. This may be detected at compile time using //! `#[cfg(target_has_atomic = "ptr")]`. -use core::any::Any; -use core::cell::CloneFromCell; -#[cfg(not(no_global_oom_handling))] -use core::clone::TrivialClone; -use core::clone::{CloneToUninit, Share, UseCloned}; -use core::cmp::Ordering; -use core::hash::{Hash, Hasher}; -use core::intrinsics::abort; -#[cfg(not(no_global_oom_handling))] -use core::iter; -use core::marker::{PhantomData, Unsize}; -use core::mem::{self, Alignment, ManuallyDrop}; -use core::num::NonZeroUsize; -use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; -#[cfg(not(no_global_oom_handling))] -use core::ops::{Residual, Try}; -use core::panic::{RefUnwindSafe, UnwindSafe}; -use core::pin::{Pin, PinSafePointer}; -use core::ptr::{self, NonNull}; -#[cfg(not(no_global_oom_handling))] -use core::slice::from_raw_parts_mut; -use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use core::sync::atomic::{self, Atomic}; -use core::{borrow, fmt, hint}; - -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; -#[cfg(not(no_global_oom_handling))] -use crate::alloc::{AllocatorNightly, handle_alloc_error}; -use crate::borrow::{Cow, ToOwned}; -use crate::boxed::Box; -use crate::rc::is_dangling; -#[cfg(not(no_global_oom_handling))] -use crate::string::String; -#[cfg(not(no_global_oom_handling))] -use crate::vec::Vec; - -/// A soft limit on the amount of references that may be made to an `Arc`. -/// -/// Going above this limit will abort your program (although not -/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. -/// Trying to go above it might call a `panic` (if not actually going above it). -/// -/// This is a global invariant, and also applies when using a compare-exchange loop. -/// -/// See comment in `Arc::clone`. -const MAX_REFCOUNT: usize = (isize::MAX) as usize; - -#[cold] -#[cfg_attr(not(panic = "immediate-abort"), inline(never))] -#[cfg_attr(panic = "immediate-abort", inline)] -#[track_caller] -fn panic_arc_overflow() -> ! { - panic!("Arc counter overflow"); -} - -#[cfg(not(sanitize = "thread"))] -macro_rules! acquire { - ($x:expr) => { - atomic::fence(Acquire) - }; -} - -// ThreadSanitizer does not support memory fences. To avoid false positive -// reports in Arc / Weak implementation use atomic loads for synchronization -// instead. -#[cfg(sanitize = "thread")] -macro_rules! acquire { - ($x:expr) => { - $x.load(Acquire) - }; -} - -/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically -/// Reference Counted'. -/// -/// The type `Arc` provides shared ownership of a value of type `T`, -/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new `Arc` instance, which points to the same allocation on the heap as the -/// source `Arc`, while increasing a reference count. When the last `Arc` -/// pointer to a given allocation is destroyed, the value stored in that allocation (often -/// referred to as "inner value") is also dropped. -/// -/// Shared references in Rust disallow mutation by default, and `Arc` is no -/// exception: you cannot generally obtain a mutable reference to something -/// inside an `Arc`. If you do need to mutate through an `Arc`, you have several options: -/// -/// 1. Use interior mutability with synchronization primitives like [`Mutex`][mutex], -/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. -/// -/// 2. Use clone-on-write semantics with [`Arc::make_mut`] which provides efficient mutation -/// without requiring interior mutability. This approach clones the data only when -/// needed (when there are multiple references) and can be more efficient when mutations -/// are infrequent. -/// -/// 3. Use [`Arc::get_mut`] when you know your `Arc` is not shared (has a reference count of 1), -/// which provides direct mutable access to the inner value without any cloning. -/// -/// ``` -/// use std::sync::Arc; -/// -/// let mut data = Arc::new(vec![1, 2, 3]); -/// -/// // This will clone the vector only if there are other references to it -/// Arc::make_mut(&mut data).push(4); -/// -/// assert_eq!(*data, vec![1, 2, 3, 4]); -/// ``` -/// -/// **Note**: This type is only available on platforms that support atomic -/// loads and stores of pointers, which includes all platforms that support -/// the `std` crate but not all those which only support [`alloc`](crate). -/// This may be detected at compile time using `#[cfg(target_has_atomic = "ptr")]`. -/// -/// ## Thread Safety -/// -/// Unlike [`Rc`], `Arc` uses atomic operations for its reference -/// counting. This means that it is thread-safe. The disadvantage is that -/// atomic operations are more expensive than ordinary memory accesses. If you -/// are not sharing reference-counted allocations between threads, consider using -/// [`Rc`] for lower overhead. [`Rc`] is a safe default, because the -/// compiler will catch any attempt to send an [`Rc`] between threads. -/// However, a library might choose `Arc` in order to give library consumers -/// more flexibility. -/// -/// `Arc` will implement [`Send`] and [`Sync`] as long as the `T` implements -/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an -/// `Arc` to make it thread-safe? This may be a bit counter-intuitive at -/// first: after all, isn't the point of `Arc` thread safety? The key is -/// this: `Arc` makes it thread safe to have multiple ownership of the same -/// data, but it doesn't add thread safety to its data. Consider -/// Arc<[RefCell\]>. [`RefCell`] isn't [`Sync`], and if `Arc` was always -/// [`Send`], Arc<[RefCell\]> would be as well. But then we'd have a problem: -/// [`RefCell`] is not thread safe; it keeps track of the borrowing count using -/// non-atomic operations. -/// -/// In the end, this means that you may need to pair `Arc` with some sort of -/// [`std::sync`] type, usually [`Mutex`][mutex]. -/// -/// ## Breaking cycles with `Weak` -/// -/// The [`downgrade`][downgrade] method can be used to create a non-owning -/// [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d -/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has -/// already been dropped. In other words, `Weak` pointers do not keep the value -/// inside the allocation alive; however, they *do* keep the allocation -/// (the backing store for the value) alive. -/// -/// A cycle between `Arc` pointers will never be deallocated. For this reason, -/// [`Weak`] is used to break cycles. For example, a tree could have -/// strong `Arc` pointers from parent nodes to children, and [`Weak`] -/// pointers from children back to their parents. -/// -/// # Cloning references -/// -/// Creating a new reference from an existing reference-counted pointer is done using the -/// `Clone` trait implemented for [`Arc`][Arc] and [`Weak`][Weak]. -/// -/// ``` -/// use std::sync::Arc; -/// let foo = Arc::new(vec![1.0, 2.0, 3.0]); -/// // The two syntaxes below are equivalent. -/// let a = foo.clone(); -/// let b = Arc::clone(&foo); -/// // a, b, and foo are all Arcs that point to the same memory location -/// ``` -/// -/// ## `Deref` behavior -/// -/// `Arc` automatically dereferences to `T` (via the [`Deref`] trait), -/// so you can call `T`'s methods on a value of type `Arc`. To avoid name -/// clashes with `T`'s methods, the methods of `Arc` itself are associated -/// functions, called using [fully qualified syntax]: -/// -/// ``` -/// use std::sync::Arc; -/// -/// let my_arc = Arc::new(()); -/// let my_weak = Arc::downgrade(&my_arc); -/// ``` -/// -/// `Arc`'s implementations of traits like `Clone` may also be called using -/// fully qualified syntax. Some people prefer to use fully qualified syntax, -/// while others prefer using method-call syntax. -/// -/// ``` -/// use std::sync::Arc; -/// -/// let arc = Arc::new(()); -/// // Method-call syntax -/// let arc2 = arc.clone(); -/// // Fully qualified syntax -/// let arc3 = Arc::clone(&arc); -/// ``` -/// -/// [`Weak`][Weak] does not auto-dereference to `T`, because the inner value may have -/// already been dropped. -/// -/// [`Rc`]: crate::rc::Rc -/// [clone]: Clone::clone -/// [mutex]: ../../std/sync/struct.Mutex.html -/// [rwlock]: ../../std/sync/struct.RwLock.html -/// [atomic]: core::sync::atomic -/// [downgrade]: Arc::downgrade -/// [upgrade]: Weak::upgrade -/// [RefCell\]: core::cell::RefCell -/// [`RefCell`]: core::cell::RefCell -/// [`std::sync`]: ../../std/sync/index.html -/// [`Arc::clone(&from)`]: Arc::clone -/// [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name -/// -/// # Examples -/// -/// Sharing some immutable data between threads: -/// -/// ``` -/// use std::sync::Arc; -/// use std::thread; -/// -/// let five = Arc::new(5); -/// -/// for _ in 0..10 { -/// let five = Arc::clone(&five); -/// -/// thread::spawn(move || { -/// println!("{five:?}"); -/// }); -/// } -/// ``` -/// -/// Sharing a mutable [`AtomicUsize`]: -/// -/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize" -/// -/// ``` -/// use std::sync::Arc; -/// use std::sync::atomic::{AtomicUsize, Ordering}; -/// use std::thread; -/// -/// let val = Arc::new(AtomicUsize::new(5)); -/// -/// for _ in 0..10 { -/// let val = Arc::clone(&val); -/// -/// thread::spawn(move || { -/// let v = val.fetch_add(1, Ordering::Relaxed); -/// println!("{v:?}"); -/// }); -/// } -/// ``` -/// -/// See the [`rc` documentation][rc_examples] for more examples of reference -/// counting in general. -/// -/// [rc_examples]: crate::rc#examples -#[doc(search_unbox)] -#[rustc_diagnostic_item = "Arc"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_insignificant_dtor] -#[diagnostic::on_move( - message = "the type `{Self}` does not implement `Copy`", - label = "this move could be avoided by cloning the original `{Self}`, which is inexpensive", - note = "consider using `Arc::clone`" -)] -pub struct Arc< - T: ?Sized, - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, -> { - ptr: NonNull>, - phantom: PhantomData>, - alloc: A, -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for Arc {} -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for Arc {} - -#[stable(feature = "catch_unwind", since = "1.9.0")] -impl UnwindSafe - for Arc -{ -} - -#[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: ?Sized, A: Allocator> CoerceUnsized> for Arc {} - -#[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: ?Sized> DispatchFromDyn> for Arc {} - -// SAFETY: `Arc::clone` doesn't access any `Cell`s which could contain the `Arc` being cloned. -#[unstable(feature = "cell_get_cloned", issue = "145329")] -unsafe impl CloneFromCell for Arc {} - -impl Arc { - unsafe fn from_inner(ptr: NonNull>) -> Self { - // SAFETY: Upheld by caller. - unsafe { Self::from_inner_in(ptr, Global) } - } - - unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { - // SAFETY: Upheld by caller. - unsafe { Self::from_ptr_in(ptr, Global) } - } -} - -impl Arc { - #[inline] - fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { - let this = mem::ManuallyDrop::new(this); - // SAFETY: Pointer is valid for reads. - (this.ptr, unsafe { ptr::read(&this.alloc) }) - } - - #[inline] - unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { - Self { ptr, phantom: PhantomData, alloc } - } - - #[inline] - unsafe fn from_ptr_in(ptr: *mut ArcInner, alloc: A) -> Self { - // SAFETY: Upheld by caller. - unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } - } -} - -/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the -/// managed allocation. -/// -/// The allocation is accessed by calling [`upgrade`] on the `Weak` -/// pointer, which returns an [Option]<[Arc]\>. -/// -/// Since a `Weak` reference does not count towards ownership, it will not -/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no -/// guarantees about the value still being present. Thus it may return [`None`] -/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation -/// itself (the backing store) from being deallocated. -/// -/// A `Weak` pointer is useful for keeping a temporary reference to the allocation -/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to -/// prevent circular references between [`Arc`] pointers, since mutual owning references -/// would never allow either [`Arc`] to be dropped. For example, a tree could -/// have strong [`Arc`] pointers from parent nodes to children, and `Weak` -/// pointers from children back to their parents. -/// -/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`]. -/// -/// [`upgrade`]: Weak::upgrade -#[stable(feature = "arc_weak", since = "1.4.0")] -#[rustc_diagnostic_item = "ArcWeak"] -pub struct Weak< - T: ?Sized, - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, -> { - // This is a `NonNull` to allow optimizing the size of this type in enums, - // but it is not necessarily a valid pointer. - // `Weak::new` sets this to `usize::MAX` so that it doesn’t need - // to allocate space on the heap. That's not a value a real pointer - // will ever have because ArcInner has alignment at least 2. - ptr: NonNull>, - alloc: A, -} - -#[stable(feature = "arc_weak", since = "1.4.0")] -unsafe impl Send for Weak {} -#[stable(feature = "arc_weak", since = "1.4.0")] -unsafe impl Sync for Weak {} - -#[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: ?Sized, A: Allocator> CoerceUnsized> for Weak {} -#[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: ?Sized> DispatchFromDyn> for Weak {} - -// SAFETY: `Weak::clone` doesn't access any `Cell`s which could contain the `Weak` being cloned. -#[unstable(feature = "cell_get_cloned", issue = "145329")] -unsafe impl CloneFromCell for Weak {} - -#[stable(feature = "arc_weak", since = "1.4.0")] -impl fmt::Debug for Weak { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "(Weak)") - } -} - -// This is repr(C) to future-proof against possible field-reordering, which -// would interfere with otherwise safe [into|from]_raw() of transmutable -// inner types. -// Unlike RcInner, repr(align(2)) is not strictly required because atomic types -// have the alignment same as its size, but we use it for consistency and clarity. -#[repr(C, align(2))] -struct ArcInner { - strong: Atomic, - - // the value usize::MAX acts as a sentinel for temporarily "locking" the - // weak count, preventing `Arc::downgrade` from racing to create new - // `Weak` references. `Arc::is_unique` (which backs `Arc::get_mut`) - // needs to observe both the strong and weak counts as indicating - // uniqueness in one logical atomic step; since they live in separate - // atomic words, it locks the weak count while reading the strong - // count to keep the two reads consistent. - weak: Atomic, - - data: T, -} - -/// Calculate layout for `ArcInner` using the inner value's layout -fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { - // Calculate layout using the given value layout. - // Previously, layout was calculated on the expression - // `&*(ptr as *const ArcInner)`, but this created a misaligned - // reference (see #54908). - Layout::new::>() - .extend(layout) - .unwrap_or_else(|_| panic!("capacity overflow")) - .0 - .pad_to_align() -} - -unsafe impl Send for ArcInner {} -unsafe impl Sync for ArcInner {} - -impl Arc { - /// Constructs a new `Arc`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(data: T) -> Arc { - // Start the weak pointer count as 1 which is the weak pointer that's - // held by all the strong pointers (kinda), see std/rc.rs for more info - let x: Box<_> = Box::new(ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data, - }); - // SAFETY: Pointer is valid. - unsafe { Self::from_inner(Box::into_non_null(x)) } - } - - /// Constructs a new `Arc` while giving you a `Weak` to the allocation, - /// to allow you to construct a `T` which holds a weak pointer to itself. - /// - /// Generally, a structure circularly referencing itself, either directly or - /// indirectly, should not hold a strong reference to itself to prevent a memory leak. - /// Using this function, you get access to the weak pointer during the - /// initialization of `T`, before the `Arc` is created, such that you can - /// clone and store it inside the `T`. - /// - /// `new_cyclic` first allocates the managed allocation for the `Arc`, - /// then calls your closure, giving it a `Weak` to this allocation, - /// and only afterwards completes the construction of the `Arc` by placing - /// the `T` returned from your closure into the allocation. - /// - /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic` - /// returns, calling [`upgrade`] on the weak reference inside your closure will - /// fail and result in a `None` value. - /// - /// # Panics - /// - /// If `data_fn` panics, the panic is propagated to the caller, and the - /// temporary [`Weak`] is dropped normally. - /// - /// # Example - /// - /// ``` - /// # #![allow(dead_code)] - /// use std::sync::{Arc, Weak}; - /// - /// struct Gadget { - /// me: Weak, - /// } - /// - /// impl Gadget { - /// /// Constructs a reference counted Gadget. - /// fn new() -> Arc { - /// // `me` is a `Weak` pointing at the new allocation of the - /// // `Arc` we're constructing. - /// Arc::new_cyclic(|me| { - /// // Create the actual struct here. - /// Gadget { me: me.clone() } - /// }) - /// } - /// - /// /// Returns a reference counted pointer to Self. - /// fn me(&self) -> Arc { - /// self.me.upgrade().unwrap() - /// } - /// } - /// ``` - /// [`upgrade`]: Weak::upgrade - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "arc_new_cyclic", since = "1.60.0")] - pub fn new_cyclic(data_fn: F) -> Arc - where - F: FnOnce(&Weak) -> T, - { - Self::new_cyclic_in(data_fn, Global) - } - - /// Constructs a new `Arc` with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut five = Arc::::new_uninit(); - /// - /// // Deferred initialization: - /// Arc::get_mut(&mut five).unwrap().write(5); - /// - /// let five = unsafe { five.assume_init() }; - /// - /// assert_eq!(*five, 5) - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "new_uninit", since = "1.82.0")] - #[must_use] - pub fn new_uninit() -> Arc> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::from_ptr(Arc::allocate_for_layout( - Layout::new::(), - |layout| Global.allocate(layout), - <*mut u8>::cast, - )) - } - } - - /// Constructs a new `Arc` with uninitialized contents, with the memory - /// being filled with `0` bytes. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let zero = Arc::::new_zeroed(); - /// let zero = unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] - #[must_use] - pub fn new_zeroed() -> Arc> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::from_ptr(Arc::allocate_for_layout( - Layout::new::(), - |layout| Global.allocate_zeroed(layout), - <*mut u8>::cast, - )) - } - } - - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then - /// `data` will be pinned in memory and unable to be moved. - #[cfg(not(no_global_oom_handling))] - #[stable(feature = "pin", since = "1.33.0")] - #[must_use] - pub fn pin(data: T) -> Pin> { - // SAFETY: We own and create the pinned pointer. - unsafe { Pin::new_unchecked(Arc::new(data)) } - } - - /// Constructs a new `Pin>`, return an error if allocation fails. - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn try_pin(data: T) -> Result>, AllocError> { - // SAFETY: We own and create the pinned pointer. - unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } - } - - /// Constructs a new `Arc`, returning an error if allocation fails. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// use std::sync::Arc; - /// - /// let five = Arc::try_new(5)?; - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn try_new(data: T) -> Result, AllocError> { - // Start the weak pointer count as 1 which is the weak pointer that's - // held by all the strong pointers (kinda), see std/rc.rs for more info - let x: Box<_> = Box::try_new(ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data, - })?; - // SAFETY: Pointer is valid. - unsafe { Ok(Self::from_inner(Box::into_non_null(x))) } - } - - /// Constructs a new `Arc` with uninitialized contents, returning an error - /// if allocation fails. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// - /// let mut five = Arc::::try_new_uninit()?; - /// - /// // Deferred initialization: - /// Arc::get_mut(&mut five).unwrap().write(5); - /// - /// let five = unsafe { five.assume_init() }; - /// - /// assert_eq!(*five, 5); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn try_new_uninit() -> Result>, AllocError> { - // ignore-tidy-undocumented-unsafe - unsafe { - Ok(Arc::from_ptr(Arc::try_allocate_for_layout( - Layout::new::(), - |layout| Global.allocate(layout), - <*mut u8>::cast, - )?)) - } - } - - /// Constructs a new `Arc` with uninitialized contents, with the memory - /// being filled with `0` bytes, returning an error if allocation fails. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature( allocator_ext)] - /// - /// use std::sync::Arc; - /// - /// let zero = Arc::::try_new_zeroed()?; - /// let zero = unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn try_new_zeroed() -> Result>, AllocError> { - // ignore-tidy-undocumented-unsafe - unsafe { - Ok(Arc::from_ptr(Arc::try_allocate_for_layout( - Layout::new::(), - |layout| Global.allocate_zeroed(layout), - <*mut u8>::cast, - )?)) - } - } -} - -impl Arc { - /// Constructs a new `Arc` in the provided allocator. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let five = Arc::new_in(5, System); - /// ``` - #[inline] - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn new_in(data: T, alloc: A) -> Arc { - // Start the weak pointer count as 1 which is the weak pointer that's - // held by all the strong pointers (kinda), see std/rc.rs for more info - let x = Box::new_in( - ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data, - }, - alloc, - ); - let (ptr, alloc) = Box::into_non_null_with_allocator(x); - // SAFETY: Pointer is valid. - unsafe { Self::from_inner_in(ptr, alloc) } - } - - /// Constructs a new `Arc` with uninitialized contents in the provided allocator. - /// - /// # Examples - /// - /// ``` - /// #![feature(get_mut_unchecked)] - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let mut five = Arc::::new_uninit_in(System); - /// - /// let five = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5) - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn new_uninit_in(alloc: A) -> Arc, A> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::from_ptr_in( - Arc::allocate_for_layout( - Layout::new::(), - |layout| alloc.allocate(layout), - <*mut u8>::cast, - ), - alloc, - ) - } - } - - /// Constructs a new `Arc` with uninitialized contents, with the memory - /// being filled with `0` bytes, in the provided allocator. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let zero = Arc::::new_zeroed_in(System); - /// let zero = unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn new_zeroed_in(alloc: A) -> Arc, A> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::from_ptr_in( - Arc::allocate_for_layout( - Layout::new::(), - |layout| alloc.allocate_zeroed(layout), - <*mut u8>::cast, - ), - alloc, - ) - } - } - - /// Constructs a new `Arc` in the given allocator while giving you a `Weak` to the allocation, - /// to allow you to construct a `T` which holds a weak pointer to itself. - /// - /// Generally, a structure circularly referencing itself, either directly or - /// indirectly, should not hold a strong reference to itself to prevent a memory leak. - /// Using this function, you get access to the weak pointer during the - /// initialization of `T`, before the `Arc` is created, such that you can - /// clone and store it inside the `T`. - /// - /// `new_cyclic_in` first allocates the managed allocation for the `Arc`, - /// then calls your closure, giving it a `Weak` to this allocation, - /// and only afterwards completes the construction of the `Arc` by placing - /// the `T` returned from your closure into the allocation. - /// - /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic_in` - /// returns, calling [`upgrade`] on the weak reference inside your closure will - /// fail and result in a `None` value. - /// - /// # Panics - /// - /// If `data_fn` panics, the panic is propagated to the caller, and the - /// temporary [`Weak`] is dropped normally. - /// - /// # Example - /// - /// See [`new_cyclic`] - /// - /// [`new_cyclic`]: Arc::new_cyclic - /// [`upgrade`]: Weak::upgrade - #[cfg(not(no_global_oom_handling))] - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn new_cyclic_in(data_fn: F, alloc: A) -> Arc - where - F: FnOnce(&Weak) -> T, - { - // Construct the inner in the "uninitialized" state with a single - // weak reference. - let (uninit_ptr, alloc) = Box::into_non_null_with_allocator(Box::new_in( - ArcInner { - strong: atomic::AtomicUsize::new(0), - weak: atomic::AtomicUsize::new(1), - data: mem::MaybeUninit::::uninit(), - }, - alloc, - )); - let init_ptr: NonNull> = uninit_ptr.cast(); - - let weak = Weak { ptr: init_ptr, alloc }; - - // It's important we don't give up ownership of the weak pointer, or - // else the memory might be freed by the time `data_fn` returns. If - // we really wanted to pass ownership, we could create an additional - // weak pointer for ourselves, but this would result in additional - // updates to the weak reference count which might not be necessary - // otherwise. - let data = data_fn(&weak); - - // Now we can properly initialize the inner value and turn our weak - // reference into a strong reference. - let inner = init_ptr.as_ptr(); - // ignore-tidy-undocumented-unsafe - unsafe { - ptr::write(&raw mut (*inner).data, data); - - // The above write to the data field must be visible to any threads which - // observe a non-zero strong count. Therefore we need at least "Release" ordering - // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`. - // - // "Acquire" ordering is not required. When considering the possible behaviors - // of `data_fn` we only need to look at what it could do with a reference to a - // non-upgradeable `Weak`: - // - It can *clone* the `Weak`, increasing the weak reference count. - // - It can drop those clones, decreasing the weak reference count (but never to zero). - // - // These side effects do not impact us in any way, and no other side effects are - // possible with safe code alone. - let prev_value = (*inner).strong.fetch_add(1, Release); - debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); - - // Strong references should collectively own a shared weak reference, - // so don't run the destructor for our old weak reference. - // Calling into_raw_with_allocator has the double effect of giving us back the allocator, - // and forgetting the weak reference. - let alloc = weak.into_raw_with_allocator().1; - - Arc::from_inner_in(init_ptr, alloc) - } - } - - /// Constructs a new `Pin>` in the provided allocator. If `T` does not implement `Unpin`, - /// then `data` will be pinned in memory and unable to be moved. - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn pin_in(data: T, alloc: A) -> Pin> - where - A: StaticAllocator, - { - // SAFETY: We own and create the pinned pointer. - unsafe { Pin::new_unchecked(Arc::new_in(data, alloc)) } - } - - /// Constructs a new `Pin>` in the provided allocator, return an error if allocation - /// fails. - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn try_pin_in(data: T, alloc: A) -> Result>, AllocError> - where - A: StaticAllocator, - { - // SAFETY: We own and create the pinned pointer. - unsafe { Ok(Pin::new_unchecked(Arc::try_new_in(data, alloc)?)) } - } - - /// Constructs a new `Arc` in the provided allocator, returning an error if allocation fails. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let five = Arc::try_new_in(5, System)?; - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn try_new_in(data: T, alloc: A) -> Result, AllocError> { - // Start the weak pointer count as 1 which is the weak pointer that's - // held by all the strong pointers (kinda), see std/rc.rs for more info - let x = Box::try_new_in( - ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data, - }, - alloc, - )?; - let (ptr, alloc) = Box::into_non_null_with_allocator(x); - // SAFETY: Pointer is valid since we created it. - Ok(unsafe { Self::from_inner_in(ptr, alloc) }) - } - - /// Constructs a new `Arc` with uninitialized contents, in the provided allocator, returning an - /// error if allocation fails. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// #![feature(get_mut_unchecked)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let mut five = Arc::::try_new_uninit_in(System)?; - /// - /// let five = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); - /// - /// five.assume_init() - /// }; - /// - /// assert_eq!(*five, 5); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { - // ignore-tidy-undocumented-unsafe - unsafe { - Ok(Arc::from_ptr_in( - Arc::try_allocate_for_layout( - Layout::new::(), - |layout| alloc.allocate(layout), - <*mut u8>::cast, - )?, - alloc, - )) - } - } - - /// Constructs a new `Arc` with uninitialized contents, with the memory - /// being filled with `0` bytes, in the provided allocator, returning an error if allocation - /// fails. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let zero = Arc::::try_new_zeroed_in(System)?; - /// let zero = unsafe { zero.assume_init() }; - /// - /// assert_eq!(*zero, 0); - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { - // ignore-tidy-undocumented-unsafe - unsafe { - Ok(Arc::from_ptr_in( - Arc::try_allocate_for_layout( - Layout::new::(), - |layout| alloc.allocate_zeroed(layout), - <*mut u8>::cast, - )?, - alloc, - )) - } - } - /// Returns the inner value, if the `Arc` has exactly one strong reference. - /// - /// Otherwise, an [`Err`] is returned with the same `Arc` that was - /// passed in. - /// - /// This will succeed even if there are outstanding weak references. - /// - /// It is strongly recommended to use [`Arc::into_inner`] instead if you don't - /// keep the `Arc` in the [`Err`] case. - /// Immediately dropping the [`Err`]-value, as the expression - /// `Arc::try_unwrap(this).ok()` does, can cause the strong count to - /// drop to zero and the inner value of the `Arc` to be dropped. - /// For instance, if two threads execute such an expression in parallel, - /// there is a race condition without the possibility of unsafety: - /// The threads could first both check whether they own the last instance - /// in `Arc::try_unwrap`, determine that they both do not, and then both - /// discard and drop their instance in the call to [`ok`][`Result::ok`]. - /// In this scenario, the value inside the `Arc` is safely destroyed - /// by exactly one of the threads, but neither thread will ever be able - /// to use the value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new(3); - /// assert_eq!(Arc::try_unwrap(x), Ok(3)); - /// - /// let x = Arc::new(4); - /// let _y = Arc::clone(&x); - /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); - /// ``` - #[inline] - #[stable(feature = "arc_unique", since = "1.4.0")] - pub fn try_unwrap(this: Self) -> Result { - if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() { - return Err(this); - } - - acquire!(this.inner().strong); - - let this = ManuallyDrop::new(this); - // SAFETY: Pointer is valid for reads, contains initialised memory, - // and not dropped multiple times (we return it). - let elem: T = unsafe { ptr::read(&this.ptr.as_ref().data) }; - // SAFETY: As above, but we explicitly drop the allocator only once - // upon creating and dropping a weak pointer. - let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator - - // Make a weak pointer to clean up the implicit strong-weak reference - let _weak = Weak { ptr: this.ptr, alloc }; - - Ok(elem) - } - - /// Returns the inner value, if the `Arc` has exactly one strong reference. - /// - /// Otherwise, [`None`] is returned and the `Arc` is dropped. - /// - /// This will succeed even if there are outstanding weak references. - /// - /// If `Arc::into_inner` is called on every clone of this `Arc`, - /// it is guaranteed that exactly one of the calls returns the inner value. - /// This means in particular that the inner value is not dropped. - /// - /// [`Arc::try_unwrap`] is conceptually similar to `Arc::into_inner`, but it - /// is meant for different use-cases. If used as a direct replacement - /// for `Arc::into_inner` anyway, such as with the expression - /// [Arc::try_unwrap]\(this).[ok][Result::ok](), then it does - /// **not** give the same guarantee as described in the previous paragraph. - /// For more information, see the examples below and read the documentation - /// of [`Arc::try_unwrap`]. - /// - /// # Examples - /// - /// Minimal example demonstrating the guarantee that `Arc::into_inner` gives. - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new(3); - /// let y = Arc::clone(&x); - /// - /// // Two threads calling `Arc::into_inner` on both clones of an `Arc`: - /// let x_thread = std::thread::spawn(|| Arc::into_inner(x)); - /// let y_thread = std::thread::spawn(|| Arc::into_inner(y)); - /// - /// let x_inner_value = x_thread.join().unwrap(); - /// let y_inner_value = y_thread.join().unwrap(); - /// - /// // One of the threads is guaranteed to receive the inner value: - /// assert!(matches!( - /// (x_inner_value, y_inner_value), - /// (None, Some(3)) | (Some(3), None) - /// )); - /// // The result could also be `(None, None)` if the threads called - /// // `Arc::try_unwrap(x).ok()` and `Arc::try_unwrap(y).ok()` instead. - /// ``` - /// - /// A more practical example demonstrating the need for `Arc::into_inner`: - /// ``` - /// use std::sync::Arc; - /// - /// // Definition of a simple singly linked list using `Arc`: - /// #[derive(Clone)] - /// struct LinkedList(Option>>); - /// struct Node(T, Option>>); - /// - /// // Dropping a long `LinkedList` relying on the destructor of `Arc` - /// // can cause a stack overflow. To prevent this, we can provide a - /// // manual `Drop` implementation that does the destruction in a loop: - /// impl Drop for LinkedList { - /// fn drop(&mut self) { - /// let mut link = self.0.take(); - /// while let Some(arc_node) = link.take() { - /// if let Some(Node(_value, next)) = Arc::into_inner(arc_node) { - /// link = next; - /// } - /// } - /// } - /// } - /// - /// // Implementation of `new` and `push` omitted - /// impl LinkedList { - /// /* ... */ - /// # fn new() -> Self { - /// # LinkedList(None) - /// # } - /// # fn push(&mut self, x: T) { - /// # self.0 = Some(Arc::new(Node(x, self.0.take()))); - /// # } - /// } - /// - /// // The following code could have still caused a stack overflow - /// // despite the manual `Drop` impl if that `Drop` impl had used - /// // `Arc::try_unwrap(arc).ok()` instead of `Arc::into_inner(arc)`. - /// - /// // Create a long list and clone it - /// let mut x = LinkedList::new(); - /// let size = 100000; - /// # let size = if cfg!(miri) { 100 } else { size }; - /// for i in 0..size { - /// x.push(i); // Adds i to the front of x - /// } - /// let y = x.clone(); - /// - /// // Drop the clones in parallel - /// let x_thread = std::thread::spawn(|| drop(x)); - /// let y_thread = std::thread::spawn(|| drop(y)); - /// x_thread.join().unwrap(); - /// y_thread.join().unwrap(); - /// ``` - #[inline] - #[stable(feature = "arc_into_inner", since = "1.70.0")] - pub fn into_inner(this: Self) -> Option { - // Make sure that the ordinary `Drop` implementation isn’t called as well - let mut this = mem::ManuallyDrop::new(this); - - // Following the implementation of `drop` and `drop_slow` - if this.inner().strong.fetch_sub(1, Release) != 1 { - return None; - } - - acquire!(this.inner().strong); - - // SAFETY: This mirrors the line - // - // unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) }; - // - // in `drop_slow`. Instead of dropping the value behind the pointer, - // it is read and eventually returned; `ptr::read` has the same - // safety conditions as `ptr::drop_in_place`. - let inner = unsafe { ptr::read(Self::get_mut_unchecked(&mut this)) }; - // SAFETY: Pointer is valid for reads. - let alloc = unsafe { ptr::read(&this.alloc) }; - - drop(Weak { ptr: this.ptr, alloc }); - - Some(inner) - } - - /// Maps the value in an `Arc`, reusing the allocation if possible. - /// - /// `f` is called on a reference to the value in the `Arc`, and the result is returned, also in - /// an `Arc`. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `Arc::map(a, f)` instead of `r.map(a)`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let r = Arc::new(7); - /// let new = Arc::map(r, |i| i + 7); - /// assert_eq!(*new, 14); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[stable(feature = "smart_pointer_map", since = "CURRENT_RUSTC_VERSION")] - pub fn map(this: Self, f: impl FnOnce(&T) -> U) -> Arc { - if size_of::() == size_of::() - && align_of::() == align_of::() - && Arc::is_unique(&this) - { - // ignore-tidy-undocumented-unsafe - unsafe { - let (ptr, alloc) = Arc::into_raw_with_allocator(this); - let value = ptr.read(); - let mut allocation = Arc::from_raw_in(ptr.cast::>(), alloc); - - Arc::get_mut_unchecked(&mut allocation).write(f(&value)); - allocation.assume_init() - } - } else { - let output = f(&*this); - let (ptr, alloc) = Arc::into_raw_with_allocator(this); - // ignore-tidy-undocumented-unsafe - unsafe { Arc::decrement_strong_count_in(ptr, &alloc) } - - Arc::new_in(output, alloc) - } - } - - /// Attempts to map the value in an `Arc`, reusing the allocation if possible. - /// - /// `f` is called on a reference to the value in the `Arc`, and if the operation succeeds, the - /// result is returned, also in an `Arc`. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `Arc::try_map(a, f)` instead of `a.try_map(f)`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// # Examples - /// - /// ``` - /// #![feature(smart_pointer_try_map)] - /// - /// use std::sync::Arc; - /// - /// let b = Arc::new(7); - /// let new = Arc::try_map(b, |&i| u32::try_from(i)).unwrap(); - /// assert_eq!(*new, 7); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "smart_pointer_try_map", issue = "144419")] - pub fn try_map( - this: Self, - f: impl FnOnce(&T) -> R, - ) -> >>::TryType - where - R: Try, - R::Residual: Residual>, - { - if size_of::() == size_of::() - && align_of::() == align_of::() - && Arc::is_unique(&this) - { - // ignore-tidy-undocumented-unsafe - unsafe { - let (ptr, alloc) = Arc::into_raw_with_allocator(this); - let value = ptr.read(); - let mut allocation = - Arc::from_raw_in(ptr.cast::>(), alloc); - - Arc::get_mut_unchecked(&mut allocation).write(f(&value)?); - try { allocation.assume_init() } - } - } else { - let output = f(&*this)?; - let (ptr, alloc) = Arc::into_raw_with_allocator(this); - // ignore-tidy-undocumented-unsafe - unsafe { Arc::decrement_strong_count_in(ptr, &alloc) } - - try { Arc::new_in(output, alloc) } - } - } -} - -impl Arc<[T]> { - /// Constructs a new atomically reference-counted slice with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut values = Arc::<[u32]>::new_uninit_slice(3); - /// - /// // Deferred initialization: - /// let data = Arc::get_mut(&mut values).unwrap(); - /// data[0].write(1); - /// data[1].write(2); - /// data[2].write(3); - /// - /// let values = unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "new_uninit", since = "1.82.0")] - #[must_use] - pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { - // ignore-tidy-undocumented-unsafe - unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } - } - - /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being - /// filled with `0` bytes. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and - /// incorrect usage of this method. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let values = Arc::<[u32]>::new_zeroed_slice(3); - /// let values = unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [0, 0, 0]) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[inline] - #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] - #[must_use] - pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::from_ptr(Arc::allocate_for_layout( - Layout::array::(len).unwrap(), - |layout| Global.allocate_zeroed(layout), - |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[mem::MaybeUninit]>, - )) - } - } -} - -impl Arc<[T], A> { - /// Constructs a new atomically reference-counted slice with uninitialized contents in the - /// provided allocator. - /// - /// # Examples - /// - /// ``` - /// #![feature(get_mut_unchecked)] - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let mut values = Arc::<[u32], _>::new_uninit_slice_in(3, System); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { - // ignore-tidy-undocumented-unsafe - unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } - } - - /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being - /// filled with `0` bytes, in the provided allocator. - /// - /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and - /// incorrect usage of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let values = Arc::<[u32], _>::new_zeroed_slice_in(3, System); - /// let values = unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [0, 0, 0]) - /// ``` - /// - /// [zeroed]: mem::MaybeUninit::zeroed - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - #[inline] - pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::from_ptr_in( - Arc::allocate_for_layout( - Layout::array::(len).unwrap(), - |layout| alloc.allocate_zeroed(layout), - |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[mem::MaybeUninit]>, - ), - alloc, - ) - } - } - - /// Converts the reference-counted slice into a reference-counted array. - /// - /// This operation does not reallocate; the underlying array of the slice is simply reinterpreted as an array type. - /// - /// # Errors - /// - /// Returns the original `Arc<[T]>` in the `Err` variant if `self.len()` does not equal `N`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc_slice_into_array)] - /// use std::sync::Arc; - /// - /// let arc_slice: Arc<[i32]> = Arc::new([1, 2, 3]); - /// - /// let arc_array: Arc<[i32; 3]> = arc_slice.into_array().unwrap(); - /// ``` - #[unstable(feature = "alloc_slice_into_array", issue = "148082")] - #[inline] - pub fn into_array(self) -> Result, Self> { - if self.len() == N { - let (ptr, alloc) = Self::into_raw_with_allocator(self); - let ptr = ptr as *const [T; N]; - - // SAFETY: The underlying array of a slice has the exact same layout as an actual array `[T; N]` if `N` is equal to the slice's length. - let me = unsafe { Arc::from_raw_in(ptr, alloc) }; - Ok(me) - } else { - Err(self) - } - } -} - -impl Arc, A> { - /// Converts to `Arc`. - /// - /// # Safety - /// - /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the inner value - /// really is in an initialized state. - /// Calling this when the content is not yet fully initialized - /// causes immediate undefined behavior. - /// - /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut five = Arc::::new_uninit(); - /// - /// // Deferred initialization: - /// Arc::get_mut(&mut five).unwrap().write(5); - /// - /// let five = unsafe { five.assume_init() }; - /// - /// assert_eq!(*five, 5) - /// ``` - #[stable(feature = "new_uninit", since = "1.82.0")] - #[must_use = "`self` will be dropped if the result is not used"] - #[inline] - pub unsafe fn assume_init(self) -> Arc { - let (ptr, alloc) = Arc::into_inner_with_allocator(self); - // ignore-tidy-undocumented-unsafe - unsafe { Arc::from_inner_in(ptr.cast(), alloc) } - } -} - -impl Arc { - /// Constructs a new `Arc` with a clone of `value`. - /// - /// # Examples - /// - /// ``` - /// #![feature(clone_from_ref)] - /// use std::sync::Arc; - /// - /// let hello: Arc = Arc::clone_from_ref("hello"); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "clone_from_ref", issue = "149075")] - pub fn clone_from_ref(value: &T) -> Arc { - Arc::clone_from_ref_in(value, Global) - } - - /// Constructs a new `Arc` with a clone of `value`, returning an error if allocation fails - /// - /// # Examples - /// - /// ``` - /// #![feature(clone_from_ref)] - /// use std::sync::Arc; - /// - /// let hello: Arc = Arc::try_clone_from_ref("hello")?; - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn try_clone_from_ref(value: &T) -> Result, AllocError> { - Arc::try_clone_from_ref_in(value, Global) - } -} - -impl Arc { - /// Constructs a new `Arc` with a clone of `value` in the provided allocator. - /// - /// # Examples - /// - /// ``` - /// #![feature(clone_from_ref)] - /// #![feature(allocator_ext)] - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let hello: Arc = Arc::clone_from_ref_in("hello", System); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn clone_from_ref_in(value: &T, alloc: A) -> Arc { - // `in_progress` drops the allocation if we panic before finishing initializing it. - let mut in_progress: UniqueArcUninit = UniqueArcUninit::new(value, alloc); - - // Initialize with clone of value. - // ignore-tidy-undocumented-unsafe - unsafe { - // Clone. If the clone panics, `in_progress` will be dropped and clean up. - value.clone_to_uninit(in_progress.data_ptr().cast()); - // Cast type of pointer, now that it is initialized. - in_progress.into_arc() - } - } - - /// Constructs a new `Arc` with a clone of `value` in the provided allocator, returning an error if allocation fails - /// - /// # Examples - /// - /// ``` - /// #![feature(clone_from_ref)] - /// #![feature(allocator_ext)] - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let hello: Arc = Arc::try_clone_from_ref_in("hello", System)?; - /// # Ok::<(), std::alloc::AllocError>(()) - /// ``` - #[unstable(feature = "clone_from_ref", issue = "149075")] - //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result, AllocError> { - // `in_progress` drops the allocation if we panic before finishing initializing it. - let mut in_progress: UniqueArcUninit = UniqueArcUninit::try_new(value, alloc)?; - - // Initialize with clone of value. - // ignore-tidy-undocumented-unsafe - let initialized_clone = unsafe { - // Clone. If the clone panics, `in_progress` will be dropped and clean up. - value.clone_to_uninit(in_progress.data_ptr().cast()); - // Cast type of pointer, now that it is initialized. - in_progress.into_arc() - }; - - Ok(initialized_clone) - } -} - -impl Arc<[mem::MaybeUninit], A> { - /// Converts to `Arc<[T]>`. - /// - /// # Safety - /// - /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the inner value - /// really is in an initialized state. - /// Calling this when the content is not yet fully initialized - /// causes immediate undefined behavior. - /// - /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut values = Arc::<[u32]>::new_uninit_slice(3); - /// - /// // Deferred initialization: - /// let data = Arc::get_mut(&mut values).unwrap(); - /// data[0].write(1); - /// data[1].write(2); - /// data[2].write(3); - /// - /// let values = unsafe { values.assume_init() }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[stable(feature = "new_uninit", since = "1.82.0")] - #[must_use = "`self` will be dropped if the result is not used"] - #[inline] - pub unsafe fn assume_init(self) -> Arc<[T], A> { - let (ptr, alloc) = Arc::into_inner_with_allocator(self); - // SAFETY: Upheld by caller. - unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } - } -} - -impl Arc { - /// Constructs an `Arc` from a raw pointer. - /// - /// The raw pointer must have been previously returned by a call to - /// [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator]. - /// - /// # Safety - /// - /// * Creating a `Arc` from a pointer other than one returned from - /// [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator] - /// is undefined behavior. - /// * If `U` is sized, it must have the same size and alignment as `T`. This - /// is trivially true if `U` is `T`. - /// * If `U` is unsized, its data pointer must have the same size and - /// alignment as `T`. This is trivially true if `Arc` was constructed - /// through `Arc` and then converted to `Arc` through an [unsized - /// coercion]. - /// * Note that if `U` or `U`'s data pointer is not `T` but has the same size - /// and alignment, this is basically like transmuting references of - /// different types. See [`mem::transmute`][transmute] for more information - /// on what restrictions apply in this case. - /// * The raw pointer must point to a block of memory allocated by the global allocator. - /// * The user of `from_raw` has to make sure a specific value of `T` is only - /// dropped once. - /// - /// This function is unsafe because improper use may lead to memory unsafety, - /// even if the returned `Arc` is never accessed. - /// - /// [into_raw]: Arc::into_raw - /// [into_raw_with_allocator]: Arc::into_raw_with_allocator - /// [transmute]: core::mem::transmute - /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new("hello".to_owned()); - /// let x_ptr = Arc::into_raw(x); - /// - /// unsafe { - /// // Convert back to an `Arc` to prevent leak. - /// let x = Arc::from_raw(x_ptr); - /// assert_eq!(&*x, "hello"); - /// - /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. - /// } - /// - /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! - /// ``` - /// - /// Convert a slice back into its original array: - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x: Arc<[u32]> = Arc::new([1, 2, 3]); - /// let x_ptr: *const [u32] = Arc::into_raw(x); - /// - /// unsafe { - /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()); - /// assert_eq!(&*x, &[1, 2, 3]); - /// } - /// ``` - #[inline] - #[stable(feature = "rc_raw", since = "1.17.0")] - pub unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Upheld by caller. - unsafe { Arc::from_raw_in(ptr, Global) } - } - - /// Consumes the `Arc`, returning the wrapped pointer. - /// - /// To avoid a memory leak the pointer must be converted back to an `Arc` using - /// [`Arc::from_raw`]. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new("hello".to_owned()); - /// let x_ptr = Arc::into_raw(x); - /// assert_eq!(unsafe { &*x_ptr }, "hello"); - /// # // Prevent leaks for Miri. - /// # drop(unsafe { Arc::from_raw(x_ptr) }); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "rc_raw", since = "1.17.0")] - #[rustc_never_returns_null_ptr] - pub fn into_raw(this: Self) -> *const T { - let this = ManuallyDrop::new(this); - Self::as_ptr(&*this) - } - - /// Increments the strong reference count on the `Arc` associated with the - /// provided pointer by one. - /// - /// # Safety - /// - /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the - /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. - /// The associated `Arc` instance must be valid (i.e. the strong count must be at - /// least 1) for the duration of this method, and `ptr` must point to a block of memory - /// allocated by the global allocator. - /// - /// [from_raw_in]: Arc::from_raw_in - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// unsafe { - /// let ptr = Arc::into_raw(five); - /// Arc::increment_strong_count(ptr); - /// - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` between threads. - /// let five = Arc::from_raw(ptr); - /// assert_eq!(2, Arc::strong_count(&five)); - /// # // Prevent leaks for Miri. - /// # Arc::decrement_strong_count(ptr); - /// } - /// ``` - #[inline] - #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] - pub unsafe fn increment_strong_count(ptr: *const T) { - // SAFETY: Upheld by caller. - unsafe { Arc::increment_strong_count_in(ptr, Global) } - } - - /// Decrements the strong reference count on the `Arc` associated with the - /// provided pointer by one. - /// - /// # Safety - /// - /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the - /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. - /// The associated `Arc` instance must be valid (i.e. the strong count must be at - /// least 1) when invoking this method, and `ptr` must point to a block of memory - /// allocated by the global allocator. This method can be used to release the final - /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been - /// released. - /// - /// [from_raw_in]: Arc::from_raw_in - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// unsafe { - /// let ptr = Arc::into_raw(five); - /// Arc::increment_strong_count(ptr); - /// - /// // Those assertions are deterministic because we haven't shared - /// // the `Arc` between threads. - /// let five = Arc::from_raw(ptr); - /// assert_eq!(2, Arc::strong_count(&five)); - /// Arc::decrement_strong_count(ptr); - /// assert_eq!(1, Arc::strong_count(&five)); - /// } - /// ``` - #[inline] - #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] - pub unsafe fn decrement_strong_count(ptr: *const T) { - // SAFETY: Upheld by caller. - unsafe { Arc::decrement_strong_count_in(ptr, Global) } - } - - /// Gets the number of strong (`Arc`) pointers to the allocation behind the given raw - /// pointer. - /// - /// This method does not consume or drop the `Arc` behind this pointer. - /// - /// # Safety - /// - /// The pointer must point to (and have valid metadata for) the value inside a live `Arc` - /// allocation, such as a pointer returned by [`Arc::into_raw`], - /// [`Arc::into_raw_with_allocator`], or [`Arc::as_ptr`]. - /// `T` must have the same alignment as that value. - /// The associated `Arc` instance must be valid (i.e. the strong count must be at - /// least 1) for the duration of this method. - /// - /// Using this method correctly also requires extra care: another thread can change the - /// strong count at any time, including between calling this method and acting on the - /// result. - /// - /// # Examples - /// - /// ``` - /// #![feature(arc_raw_get_strong)] - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let _also_five = Arc::clone(&five); - /// let ptr = Arc::into_raw(five); - /// - /// unsafe { - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` between threads. - /// assert_eq!(2, Arc::strong_count_from_raw(ptr)); - /// - /// // Convert back to an `Arc` to avoid leaking memory. - /// let five = Arc::from_raw(ptr); - /// assert_eq!(2, Arc::strong_count(&five)); - /// } - /// ``` - #[inline] - #[must_use] - #[unstable(feature = "arc_raw_get_strong", issue = "157021")] - pub unsafe fn strong_count_from_raw(ptr: *const T) -> usize { - // SAFETY: Upheld by caller. - let offset = unsafe { data_offset(ptr) }; - // Reverse the offset to find the original ArcInner. - // SAFETY: Caller ensures this pointer was to an `Arc` allocation, - // so offsetting must be inbounds. - let arc_ptr = unsafe { ptr.byte_sub(offset) as *mut ArcInner }; - // SAFETY: Per the above, an `ArcInner` is stored here. - unsafe { (*arc_ptr).strong.load(Relaxed) } - } -} - -impl Arc { - /// Returns a reference to the underlying allocator. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This - /// is so that there is no conflict with a method on the inner type. - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn allocator(this: &Self) -> &A { - &this.alloc - } - - /// Consumes the `Arc`, returning the wrapped pointer and allocator. - /// - /// To avoid a memory leak the pointer must be converted back to an `Arc` using - /// [`Arc::from_raw_in`]. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let x = Arc::new_in("hello".to_owned(), System); - /// let (ptr, alloc) = Arc::into_raw_with_allocator(x); - /// assert_eq!(unsafe { &*ptr }, "hello"); - /// let x = unsafe { Arc::from_raw_in(ptr, alloc) }; - /// assert_eq!(&*x, "hello"); - /// ``` - #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { - let this = mem::ManuallyDrop::new(this); - let ptr = Self::as_ptr(&this); - // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped - let alloc = unsafe { ptr::read(&this.alloc) }; - (ptr, alloc) - } - - /// Provides a raw pointer to the data. - /// - /// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for - /// as long as there are strong counts in the `Arc`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new("hello".to_owned()); - /// let y = Arc::clone(&x); - /// let x_ptr = Arc::as_ptr(&x); - /// assert_eq!(x_ptr, Arc::as_ptr(&y)); - /// assert_eq!(unsafe { &*x_ptr }, "hello"); - /// ``` - #[must_use] - #[stable(feature = "rc_as_ptr", since = "1.45.0")] - #[rustc_never_returns_null_ptr] - pub fn as_ptr(this: &Self) -> *const T { - let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); - - // SAFETY: This cannot go through Deref::deref or ArcInnerPtr::inner because - // this is required to retain raw/mut provenance such that e.g. `get_mut` can - // write through the pointer after the Arc is recovered through `from_raw`. - unsafe { &raw mut (*ptr).data } - } - - /// Constructs an `Arc` from a raw pointer. - /// - /// The raw pointer must have been previously returned by a call to [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator]. - /// - /// # Safety - /// - /// * Creating a `Arc` from a pointer other than one returned from - /// [`Arc::into_raw`][into_raw] or [`Arc::into_raw_with_allocator`][into_raw_with_allocator] - /// is undefined behavior. - /// * If `U` is sized, it must have the same size and alignment as `T`. This - /// is trivially true if `U` is `T`. - /// * If `U` is unsized, its data pointer must have the same size and - /// alignment as `T`. This is trivially true if `Arc` was constructed - /// through `Arc` and then converted to `Arc` through an [unsized - /// coercion]. - /// * Note that if `U` or `U`'s data pointer is not `T` but has the same size - /// and alignment, this is basically like transmuting references of - /// different types. See [`mem::transmute`][transmute] for more information - /// on what restrictions apply in this case. - /// * The raw pointer must point to a block of memory allocated by `alloc` - /// * The user of `from_raw` has to make sure a specific value of `T` is only - /// dropped once. - /// - /// This function is unsafe because improper use may lead to memory unsafety, - /// even if the returned `Arc` is never accessed. - /// - /// [into_raw]: Arc::into_raw - /// [into_raw_with_allocator]: Arc::into_raw_with_allocator - /// [transmute]: core::mem::transmute - /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let x = Arc::new_in("hello".to_owned(), System); - /// let (x_ptr, alloc) = Arc::into_raw_with_allocator(x); - /// - /// unsafe { - /// // Convert back to an `Arc` to prevent leak. - /// let x = Arc::from_raw_in(x_ptr, System); - /// assert_eq!(&*x, "hello"); - /// - /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. - /// } - /// - /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! - /// ``` - /// - /// Convert a slice back into its original array: - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let x: Arc<[u32], _> = Arc::new_in([1, 2, 3], System); - /// let x_ptr: *const [u32] = Arc::into_raw_with_allocator(x).0; - /// - /// unsafe { - /// let x: Arc<[u32; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); - /// assert_eq!(&*x, &[1, 2, 3]); - /// } - /// ``` - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { - // SAFETY: Upheld by caller. - unsafe { - let offset = data_offset(ptr); - - // Reverse the offset to find the original ArcInner. - let arc_ptr = ptr.byte_sub(offset) as *mut ArcInner; - - Self::from_ptr_in(arc_ptr, alloc) - } - } - - /// Creates a new [`Weak`] pointer to this allocation. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// let weak_five = Arc::downgrade(&five); - /// ``` - #[must_use = "this returns a new `Weak` pointer, \ - without modifying the original `Arc`"] - #[stable(feature = "arc_weak", since = "1.4.0")] - pub fn downgrade(this: &Self) -> Weak - where - A: AllocatorClone, - { - // This Relaxed is OK because we're checking the value in the CAS - // below. - let mut cur = this.inner().weak.load(Relaxed); - - loop { - // check if the weak counter is currently "locked"; if so, spin. - if cur == usize::MAX { - hint::spin_loop(); - cur = this.inner().weak.load(Relaxed); - continue; - } - - // We can't allow the refcount to increase much past `MAX_REFCOUNT`. - if cur > MAX_REFCOUNT { - panic_arc_overflow(); - } - // NOTE: this code currently ignores the possibility of overflow - // into usize::MAX; in general both Rc and Arc need to be adjusted - // to deal with overflow. - - // Unlike with Clone(), we need this to be an Acquire read to - // synchronize with the write coming from `is_unique`, so that the - // events prior to that write happen before this read. - match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { - Ok(_) => { - // Make sure we do not create a dangling Weak - debug_assert!(!is_dangling(this.ptr.as_ptr())); - return Weak { ptr: this.ptr, alloc: this.alloc.clone() }; - } - Err(old) => cur = old, - } - } - } - - /// Gets the number of [`Weak`] pointers to this allocation. - /// - /// # Safety - /// - /// This method by itself is safe, but using it correctly requires extra care. - /// Another thread can change the weak count at any time, - /// including potentially between calling this method and acting on the result. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let _weak_five = Arc::downgrade(&five); - /// - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` or `Weak` between threads. - /// assert_eq!(1, Arc::weak_count(&five)); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "arc_counts", since = "1.15.0")] - pub fn weak_count(this: &Self) -> usize { - let cnt = this.inner().weak.load(Relaxed); - // If the weak count is currently locked, the value of the - // count was 0 just before taking the lock. - if cnt == usize::MAX { 0 } else { cnt - 1 } - } - - /// Gets the number of strong (`Arc`) pointers to this allocation. - /// - /// # Safety - /// - /// This method by itself is safe, but using it correctly requires extra care. - /// Another thread can change the strong count at any time, - /// including potentially between calling this method and acting on the result. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let _also_five = Arc::clone(&five); - /// - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` between threads. - /// assert_eq!(2, Arc::strong_count(&five)); - /// ``` - #[inline] - #[must_use] - #[stable(feature = "arc_counts", since = "1.15.0")] - pub fn strong_count(this: &Self) -> usize { - this.inner().strong.load(Relaxed) - } - - /// Increments the strong reference count on the `Arc` associated with the - /// provided pointer by one. - /// - /// # Safety - /// - /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the - /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. - /// The associated `Arc` instance must be valid (i.e. the strong count must be at - /// least 1) for the duration of this method, and `ptr` must point to a block of memory - /// allocated by `alloc`. - /// - /// [from_raw_in]: Arc::from_raw_in - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let five = Arc::new_in(5, System); - /// - /// unsafe { - /// let (ptr, _alloc) = Arc::into_raw_with_allocator(five); - /// Arc::increment_strong_count_in(ptr, System); - /// - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` between threads. - /// let five = Arc::from_raw_in(ptr, System); - /// assert_eq!(2, Arc::strong_count(&five)); - /// # // Prevent leaks for Miri. - /// # Arc::decrement_strong_count_in(ptr, System); - /// } - /// ``` - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A) - where - A: AllocatorClone, - { - // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop - // SAFETY: Upheld by caller. - let arc = unsafe { mem::ManuallyDrop::new(Arc::from_raw_in(ptr, alloc)) }; - // Now increase refcount, but don't drop new refcount either - let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); - } - - /// Decrements the strong reference count on the `Arc` associated with the - /// provided pointer by one. - /// - /// # Safety - /// - /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the - /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. - /// The associated `Arc` instance must be valid (i.e. the strong count must be at - /// least 1) when invoking this method, and `ptr` must point to a block of memory - /// allocated by `alloc`. This method can be used to release the final - /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been - /// released. - /// - /// [from_raw_in]: Arc::from_raw_in - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Arc; - /// use std::alloc::System; - /// - /// let five = Arc::new_in(5, System); - /// - /// unsafe { - /// let (ptr, _alloc) = Arc::into_raw_with_allocator(five); - /// Arc::increment_strong_count_in(ptr, System); - /// - /// // Those assertions are deterministic because we haven't shared - /// // the `Arc` between threads. - /// let five = Arc::from_raw_in(ptr, System); - /// assert_eq!(2, Arc::strong_count(&five)); - /// Arc::decrement_strong_count_in(ptr, System); - /// assert_eq!(1, Arc::strong_count(&five)); - /// } - /// ``` - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { - // SAFETY: Upheld by caller. - unsafe { drop(Arc::from_raw_in(ptr, alloc)) }; - } - - #[inline] - fn inner(&self) -> &ArcInner { - // SAFETY: While this arc is alive we're guaranteed - // that the inner pointer is valid. Furthermore, we know that the - // `ArcInner` structure itself is `Sync` if the inner data is - // `Sync` as well, so we're ok loaning out an immutable pointer to these - // contents. - unsafe { self.ptr.as_ref() } - } - - // Non-inlined part of `drop`. - #[inline(never)] - unsafe fn drop_slow(&mut self) { - // Drop the weak ref collectively held by all strong references when this - // variable goes out of scope. This ensures that the memory is deallocated - // even if the destructor of `T` panics. - // Take a reference to `self.alloc` instead of cloning because 1. it'll last long - // enough, and 2. you should be able to drop `Arc`s with unclonable allocators - let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; - - // Destroy the data at this time, even though we must not free the box - // allocation itself (there might still be weak pointers lying around). - // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. - // ignore-tidy-undocumented-unsafe - unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; - } - - /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to - /// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let same_five = Arc::clone(&five); - /// let other_five = Arc::new(5); - /// - /// assert!(Arc::ptr_eq(&five, &same_five)); - /// assert!(!Arc::ptr_eq(&five, &other_five)); - /// ``` - /// - /// [`ptr::eq`]: core::ptr::eq "ptr::eq" - #[inline] - #[must_use] - #[stable(feature = "ptr_eq", since = "1.17.0")] - pub fn ptr_eq(this: &Self, other: &Self) -> bool { - ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr()) - } -} - -impl Arc { - /// Allocates an `ArcInner` with sufficient space for - /// a possibly-unsized inner value where the value has the layout provided. - /// - /// The function `mem_to_arcinner` is called with the data pointer - /// and must return back a (potentially fat)-pointer for the `ArcInner`. - #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_layout( - value_layout: Layout, - allocate: impl FnOnce(Layout) -> Result, AllocError>, - mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, - ) -> *mut ArcInner { - let layout = arcinner_layout_for_value_layout(value_layout); - - let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); - - // ignore-tidy-undocumented-unsafe - unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) } - } - - /// Allocates an `ArcInner` with sufficient space for - /// a possibly-unsized inner value where the value has the layout provided, - /// returning an error if allocation fails. - /// - /// The function `mem_to_arcinner` is called with the data pointer - /// and must return back a (potentially fat)-pointer for the `ArcInner`. - unsafe fn try_allocate_for_layout( - value_layout: Layout, - allocate: impl FnOnce(Layout) -> Result, AllocError>, - mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, - ) -> Result<*mut ArcInner, AllocError> { - let layout = arcinner_layout_for_value_layout(value_layout); - - let ptr = allocate(layout)?; - - // ignore-tidy-undocumented-unsafe - let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }; - - Ok(inner) - } - - unsafe fn initialize_arcinner( - ptr: NonNull<[u8]>, - layout: Layout, - mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, - ) -> *mut ArcInner { - let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); - // SAFETY: Upheld by caller. - debug_assert_eq!(unsafe { Layout::for_value_raw(inner) }, layout); - - // ignore-tidy-undocumented-unsafe - unsafe { - (&raw mut (*inner).strong).write(atomic::AtomicUsize::new(1)); - (&raw mut (*inner).weak).write(atomic::AtomicUsize::new(1)); - } - - inner - } -} - -impl Arc { - /// Allocates an `ArcInner` with sufficient space for an unsized inner value. - #[inline] - #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut ArcInner { - // Allocate for the `ArcInner` using the given value. - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::allocate_for_layout( - Layout::for_value_raw(ptr), - |layout| alloc.allocate(layout), - |mem| mem.with_metadata_of(ptr as *const ArcInner), - ) - } - } - - #[cfg(not(no_global_oom_handling))] - fn from_box_in(src: Box) -> Arc { - // ignore-tidy-undocumented-unsafe - unsafe { - let value_size = size_of_val(&*src); - let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); - - // Copy value as bytes - ptr::copy_nonoverlapping( - (&raw const *src) as *const u8, - (&raw mut (*ptr).data) as *mut u8, - value_size, - ); - - // Free the allocation without dropping its contents - let (bptr, alloc) = Box::into_raw_with_allocator(src); - let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop, &alloc); - drop(src); - - Self::from_ptr_in(ptr, alloc) - } - } -} - -impl Arc<[T]> { - /// Allocates an `ArcInner<[T]>` with the given length. - #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { - // ignore-tidy-undocumented-unsafe - unsafe { - Self::allocate_for_layout( - Layout::array::(len).unwrap(), - |layout| Global.allocate(layout), - |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[T]>, - ) - } - } - - /// Copy elements from slice into newly allocated `Arc<[T]>` - /// - /// Unsafe because the caller must either take ownership, bind `T: Copy` or - /// bind `T: TrivialClone`. - #[cfg(not(no_global_oom_handling))] - unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { - // ignore-tidy-undocumented-unsafe - unsafe { - let ptr = Self::allocate_for_slice(v.len()); - - ptr::copy_nonoverlapping(v.as_ptr(), (&raw mut (*ptr).data) as *mut T, v.len()); - - Self::from_ptr(ptr) - } - } - - /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. - /// - /// Behavior is undefined should the size be wrong. - #[cfg(not(no_global_oom_handling))] - unsafe fn from_iter_exact(iter: impl Iterator, len: usize) -> Arc<[T]> { - // Panic guard while cloning T elements. - // In the event of a panic, elements that have been written - // into the new ArcInner will be dropped, then the memory freed. - struct Guard { - mem: NonNull, - elems: *mut T, - layout: Layout, - n_elems: usize, - } - - impl Drop for Guard { - fn drop(&mut self) { - // ignore-tidy-undocumented-unsafe - unsafe { - let slice = from_raw_parts_mut(self.elems, self.n_elems); - ptr::drop_in_place(slice); - - Global.deallocate(self.mem, self.layout); - } - } - } - - // ignore-tidy-undocumented-unsafe - unsafe { - let ptr = Self::allocate_for_slice(len); - - let mem = ptr as *mut _ as *mut u8; - let layout = Layout::for_value_raw(ptr); - - // Pointer to first element - let elems = (&raw mut (*ptr).data) as *mut T; - - let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; - - for (i, item) in iter.enumerate() { - ptr::write(elems.add(i), item); - guard.n_elems += 1; - } - - // All clear. Forget the guard so it doesn't free the new ArcInner. - mem::forget(guard); - - Self::from_ptr(ptr) - } - } -} - -impl Arc<[T], A> { - /// Allocates an `ArcInner<[T]>` with the given length. - #[inline] - #[cfg(not(no_global_oom_handling))] - unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut ArcInner<[T]> { - // ignore-tidy-undocumented-unsafe - unsafe { - Arc::allocate_for_layout( - Layout::array::(len).unwrap(), - |layout| alloc.allocate(layout), - |mem| mem.cast::().cast_slice(len) as *mut ArcInner<[T]>, - ) - } - } -} - -/// Specialization trait used for `From<&[T]>`. -#[cfg(not(no_global_oom_handling))] -trait ArcFromSlice { - fn from_slice(slice: &[T]) -> Self; -} - -#[cfg(not(no_global_oom_handling))] -impl ArcFromSlice for Arc<[T]> { - #[inline] - default fn from_slice(v: &[T]) -> Self { - // ignore-tidy-undocumented-unsafe - unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } - } -} - -#[cfg(not(no_global_oom_handling))] -impl ArcFromSlice for Arc<[T]> { - #[inline] - fn from_slice(v: &[T]) -> Self { - // SAFETY: `T` implements `TrivialClone`, so this is sound and equivalent - // to the above. - unsafe { Arc::copy_from_slice(v) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Arc { - /// Makes a clone of the `Arc` pointer. - /// - /// This creates another pointer to the same allocation, increasing the - /// strong reference count. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// let _ = Arc::clone(&five); - /// ``` - #[inline] - fn clone(&self) -> Arc { - // Using a relaxed ordering is alright here, as knowledge of the - // original reference prevents other threads from erroneously deleting - // the object. - // - // As explained in the [Boost documentation][1], Increasing the - // reference counter can always be done with memory_order_relaxed: New - // references to an object can only be formed from an existing - // reference, and passing an existing reference from one thread to - // another must already provide any required synchronization. - // - // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - let old_size = self.inner().strong.fetch_add(1, Relaxed); - - // However we need to guard against massive refcounts in case someone is `mem::forget`ing - // Arcs. If we don't do this the count can overflow and users will use-after free. This - // branch will never be taken in any realistic program. We abort because such a program is - // incredibly degenerate, and we don't care to support it. - // - // This check is not 100% water-proof: we error when the refcount grows beyond `isize::MAX`. - // But we do that check *after* having done the increment, so there is a chance here that - // the worst already happened and we actually do overflow the `usize` counter. However, that - // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment - // above and the `abort` below, which seems exceedingly unlikely. - // - // This is a global invariant, and also applies when using a compare-exchange loop to increment - // counters in other methods. - // Otherwise, the counter could be brought to an almost-overflow using a compare-exchange loop, - // and then overflow using a few `fetch_add`s. - if old_size > MAX_REFCOUNT { - abort(); - } - - // SAFETY: Pointer is valid & allocator corresponds to the one used to allocate it. - unsafe { Self::from_inner_in(self.ptr, self.alloc.clone()) } - } -} - -#[unstable(feature = "ergonomic_clones", issue = "132290")] -impl UseCloned for Arc {} - -#[unstable(feature = "share_trait", issue = "156756")] -impl Share for Arc {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Deref for Arc { - type Target = T; - - #[inline] - fn deref(&self) -> &T { - &self.inner().data - } -} - -// The API of this pointer type enforces that if the `T` is pinned, then *all* -// clones of this `Arc` are wrapped as `Pin>`. Since an `&Arc` -// could be used to obtain an `Arc` that is not wrapped in `Pin` (and later -// used with `Arc::get_mut`), this means that this type treats `&Arc` as -// evidence that the `T` is not pinned. The implementations of various traits -// are written accordingly. Since this type is not fundamental, downstream -// crates cannot provide malicious implementations of any of the traits relevant -// for `Pin`. -#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinSafePointer for Arc {} - -#[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl DerefPure for Arc {} - -#[unstable(feature = "legacy_receiver_trait", issue = "none")] -impl LegacyReceiver for Arc {} - -#[cfg(not(no_global_oom_handling))] -impl Arc { - /// Makes a mutable reference into the given `Arc`. - /// - /// If there are other `Arc` pointers to the same allocation, then `make_mut` will - /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also - /// referred to as clone-on-write. - /// - /// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`] - /// pointers, then the [`Weak`] pointers will be dissociated and the inner value will not - /// be cloned. - /// - /// See also [`get_mut`], which will fail rather than cloning the inner value - /// or dissociating [`Weak`] pointers. - /// - /// [`clone`]: Clone::clone - /// [`get_mut`]: Arc::get_mut - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut data = Arc::new(5); - /// - /// *Arc::make_mut(&mut data) += 1; // Won't clone anything - /// let mut other_data = Arc::clone(&data); // Won't clone inner data - /// *Arc::make_mut(&mut data) += 1; // Clones inner data - /// *Arc::make_mut(&mut data) += 1; // Won't clone anything - /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything - /// - /// // Now `data` and `other_data` point to different allocations. - /// assert_eq!(*data, 8); - /// assert_eq!(*other_data, 12); - /// ``` - /// - /// [`Weak`] pointers will be dissociated: - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut data = Arc::new(75); - /// let weak = Arc::downgrade(&data); - /// - /// assert!(75 == *data); - /// assert!(75 == *weak.upgrade().unwrap()); - /// - /// *Arc::make_mut(&mut data) += 1; - /// - /// assert!(76 == *data); - /// assert!(weak.upgrade().is_none()); - /// ``` - #[inline] - #[stable(feature = "arc_unique", since = "1.4.0")] - pub fn make_mut(this: &mut Self) -> &mut T { - let size_of_val = size_of_val::(&**this); - - // Note that we hold both a strong reference and a weak reference. - // Thus, releasing our strong reference only will not, by itself, cause - // the memory to be deallocated. - // - // Use Acquire to ensure that we see any writes to `weak` that happen - // before release writes (i.e., decrements) to `strong`. Since we hold a - // weak count, there's no chance the ArcInner itself could be - // deallocated. - if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { - // Another strong pointer exists, so we must clone. - *this = Arc::clone_from_ref_in(&**this, this.alloc.clone()); - } else if this.inner().weak.load(Relaxed) != 1 { - // Relaxed suffices in the above because this is fundamentally an - // optimization: we are always racing with weak pointers being - // dropped. Worst case, we end up allocated a new Arc unnecessarily. - - // We removed the last strong ref, but there are additional weak - // refs remaining. We'll move the contents to a new Arc, and - // invalidate the other weak refs. - - // Note that it is not possible for the read of `weak` to yield - // usize::MAX (i.e., locked), since the weak count can only be - // locked by a thread with a strong reference. - - // Guard against panics while using the allocator. - // If we unwind before the Arc is overwritten, we expose a strong - // count of 0, resulting in a UAF (#155746, #157203). - // Until the new Arc is written, the old Arc must remain valid - struct Guard<'a, T: ?Sized> { - inner: &'a ArcInner, - } - impl<'a, T: ?Sized> Drop for Guard<'a, T> { - fn drop(&mut self) { - self.inner.strong.store(1, Release); - } - } - let guard = Guard { inner: this.inner() }; - - // Can just steal the data, all that's left is Weaks - // Note that this can panic in two ways: - // - The allocation can fail - // - The allocator clone can fail - let mut in_progress: UniqueArcUninit = - UniqueArcUninit::new(&**this, this.alloc.clone()); - - // ignore-tidy-undocumented-unsafe - unsafe { - // Initialize `in_progress` with move of **this. - // We have to express this in terms of bytes because `T: ?Sized`; there is no - // operation that just copies a value based on its `size_of_val()`. - ptr::copy_nonoverlapping( - ptr::from_ref(&**this).cast::(), - in_progress.data_ptr().cast::(), - size_of_val, - ); - - // We are now safe from panics. - mem::forget(guard); - - // Materialize our own implicit weak pointer, so that it can clean - // up the ArcInner as needed. - // Make sure the allocator is not leaked when the Arc is overwritten. - // Only drop at the end of the scope to avoid panics. - let _weak = Weak { ptr: this.ptr, alloc: ptr::read(&this.alloc) }; - - ptr::write(this, in_progress.into_arc()); - } - } else { - // We were the sole reference of either kind; bump back up the - // strong ref count. - this.inner().strong.store(1, Release); - } - - // SAFETY: As with `get_mut()`, our reference was - // either unique to begin with, or became one upon cloning the contents. - unsafe { Self::get_mut_unchecked(this) } - } -} - -impl Arc { - /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the - /// clone. - /// - /// Assuming `arc_t` is of type `Arc`, this function is functionally equivalent to - /// `(*arc_t).clone()`, but will avoid cloning the inner value where possible. - /// - /// # Examples - /// - /// ``` - /// # use std::{ptr, sync::Arc}; - /// let inner = String::from("test"); - /// let ptr = inner.as_ptr(); - /// - /// let arc = Arc::new(inner); - /// let inner = Arc::unwrap_or_clone(arc); - /// // The inner value was not cloned - /// assert!(ptr::eq(ptr, inner.as_ptr())); - /// - /// let arc = Arc::new(inner); - /// let arc2 = arc.clone(); - /// let inner = Arc::unwrap_or_clone(arc); - /// // Because there were 2 references, we had to clone the inner value. - /// assert!(!ptr::eq(ptr, inner.as_ptr())); - /// // `arc2` is the last reference, so when we unwrap it we get back - /// // the original `String`. - /// let inner = Arc::unwrap_or_clone(arc2); - /// assert!(ptr::eq(ptr, inner.as_ptr())); - /// ``` - #[inline] - #[stable(feature = "arc_unwrap_or_clone", since = "1.76.0")] - pub fn unwrap_or_clone(this: Self) -> T { - Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) - } -} - -impl Arc { - /// Returns a mutable reference into the given `Arc`, if there are - /// no other `Arc` or [`Weak`] pointers to the same allocation. - /// - /// Returns [`None`] otherwise, because it is not safe to - /// mutate a shared value. - /// - /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when there are other `Arc` pointers. - /// - /// [make_mut]: Arc::make_mut - /// [clone]: Clone::clone - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut x = Arc::new(3); - /// *Arc::get_mut(&mut x).unwrap() = 4; - /// assert_eq!(*x, 4); - /// - /// let _y = Arc::clone(&x); - /// assert!(Arc::get_mut(&mut x).is_none()); - /// ``` - #[inline] - #[stable(feature = "arc_unique", since = "1.4.0")] - pub fn get_mut(this: &mut Self) -> Option<&mut T> { - if Self::is_unique(this) { - // SAFETY: We're guaranteed that the pointer - // returned is the *only* pointer that will ever be returned to T. Our - // reference count is guaranteed to be 1 at this point, and we required - // the Arc itself to be `mut`, so we're returning the only possible - // reference to the inner data. - unsafe { Some(Arc::get_mut_unchecked(this)) } - } else { - None - } - } - - /// Returns a mutable reference into the given `Arc`, - /// without any check. - /// - /// See also [`get_mut`], which is safe and does appropriate checks. - /// - /// [`get_mut`]: Arc::get_mut - /// - /// # Safety - /// - /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then - /// they must not be dereferenced or have active borrows for the duration - /// of the returned borrow, and their inner type must be exactly the same as the - /// inner type of this Arc (including lifetimes). This is trivially the case if no - /// such pointers exist, for example immediately after `Arc::new`. - /// - /// # Examples - /// - /// ``` - /// #![feature(get_mut_unchecked)] - /// - /// use std::sync::Arc; - /// - /// let mut x = Arc::new(String::new()); - /// unsafe { - /// Arc::get_mut_unchecked(&mut x).push_str("foo") - /// } - /// assert_eq!(*x, "foo"); - /// ``` - /// Other `Arc` pointers to the same allocation must be to the same type. - /// ```no_run - /// #![feature(get_mut_unchecked)] - /// - /// use std::sync::Arc; - /// - /// let x: Arc = Arc::from("Hello, world!"); - /// let mut y: Arc<[u8]> = x.clone().into(); - /// unsafe { - /// // this is Undefined Behavior, because x's inner type is str, not [u8] - /// Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 - /// } - /// println!("{}", &*x); // Invalid UTF-8 in a str - /// ``` - /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. - /// ```no_run - /// #![feature(get_mut_unchecked)] - /// - /// use std::sync::Arc; - /// - /// let x: Arc<&str> = Arc::new("Hello, world!"); - /// { - /// let s = String::from("Oh, no!"); - /// let mut y: Arc<&str> = x.clone(); - /// unsafe { - /// // this is Undefined Behavior, because x's inner type - /// // is &'long str, not &'short str - /// *Arc::get_mut_unchecked(&mut y) = &s; - /// } - /// } - /// println!("{}", &*x); // Use-after-free - /// ``` - #[inline] - #[unstable(feature = "get_mut_unchecked", issue = "63292")] - pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { - // We are careful to *not* create a reference covering the "count" fields, as - // this would alias with concurrent access to the reference counts (e.g. by `Weak`). - // ignore-tidy-undocumented-unsafe - unsafe { &mut (*this.ptr.as_ptr()).data } - } - - /// Determine whether this is the unique reference to the underlying data. - /// - /// Returns `true` if there are no other `Arc` or [`Weak`] pointers to the same allocation; - /// returns `false` otherwise. - /// - /// If this function returns `true`, then is guaranteed to be safe to call [`get_mut_unchecked`] - /// on this `Arc`, so long as no clones occur in between. - /// - /// # Examples - /// - /// ``` - /// #![feature(arc_is_unique)] - /// - /// use std::sync::Arc; - /// - /// let x = Arc::new(3); - /// assert!(Arc::is_unique(&x)); - /// - /// let y = Arc::clone(&x); - /// assert!(!Arc::is_unique(&x)); - /// drop(y); - /// - /// // Weak references also count, because they could be upgraded at any time. - /// let z = Arc::downgrade(&x); - /// assert!(!Arc::is_unique(&x)); - /// ``` - /// - /// # Pointer invalidation - /// - /// This function will always return the same value as `Arc::get_mut(arc).is_some()`. However, - /// unlike that operation it does not produce any mutable references to the underlying data, - /// meaning no pointers to the data inside the `Arc` are invalidated by the call. Thus, the - /// following code is valid, even though it would be UB if it used `Arc::get_mut`: - /// - /// ``` - /// #![feature(arc_is_unique)] - /// - /// use std::sync::Arc; - /// - /// let arc = Arc::new(5); - /// let pointer: *const i32 = &*arc; - /// assert!(Arc::is_unique(&arc)); - /// assert_eq!(unsafe { *pointer }, 5); - /// ``` - /// - /// # Atomic orderings - /// - /// Concurrent drops to other `Arc` pointers to the same allocation will synchronize with this - /// call - that is, this call performs an `Acquire` operation on the underlying strong and weak - /// ref counts. This ensures that calling `get_mut_unchecked` is safe. - /// - /// Note that this operation requires locking the weak ref count, so concurrent calls to - /// `downgrade` may spin-loop for a short period of time. - /// - /// [`get_mut_unchecked`]: Self::get_mut_unchecked - #[inline] - #[unstable(feature = "arc_is_unique", issue = "138938")] - pub fn is_unique(this: &Self) -> bool { - // lock the weak pointer count if we appear to be the sole weak pointer - // holder. - // - // The acquire label here ensures a happens-before relationship with any - // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements - // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded - // weak ref was never dropped, the CAS here will fail so we do not care to synchronize. - if this.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { - // This needs to be an `Acquire` to synchronize with the decrement of the `strong` - // counter in `drop` -- the only access that happens when any but the last reference - // is being dropped. - let unique = this.inner().strong.load(Acquire) == 1; - - // The release write here synchronizes with a read in `downgrade`, - // effectively preventing the above read of `strong` from happening - // after the write. - this.inner().weak.store(1, Release); // release the lock - unique - } else { - false - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { - /// Drops the `Arc`. - /// - /// This will decrement the strong reference count. If the strong reference - /// count reaches zero then the only other references (if any) are - /// [`Weak`], so we `drop` the inner value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// struct Foo; - /// - /// impl Drop for Foo { - /// fn drop(&mut self) { - /// println!("dropped!"); - /// } - /// } - /// - /// let foo = Arc::new(Foo); - /// let foo2 = Arc::clone(&foo); - /// - /// drop(foo); // Doesn't print anything - /// drop(foo2); // Prints "dropped!" - /// ``` - #[inline] - fn drop(&mut self) { - // Because `fetch_sub` is already atomic, we do not need to synchronize - // with other threads unless we are going to delete the object. This - // same logic applies to the below `fetch_sub` to the `weak` count. - if self.inner().strong.fetch_sub(1, Release) != 1 { - return; - } - - // This fence is needed to prevent reordering of use of the data and - // deletion of the data. Because it is marked `Release`, the decreasing - // of the reference count synchronizes with this `Acquire` fence. This - // means that use of the data happens before decreasing the reference - // count, which happens before this fence, which happens before the - // deletion of the data. - // - // As explained in the [Boost documentation][1], - // - // > It is important to enforce any possible access to the object in one - // > thread (through an existing reference) to *happen before* deleting - // > the object in a different thread. This is achieved by a "release" - // > operation after dropping a reference (any access to the object - // > through this reference must obviously happened before), and an - // > "acquire" operation before deleting the object. - // - // In particular, while the contents of an Arc are usually immutable, it's - // possible to have interior writes to something like a Mutex. Since a - // Mutex is not acquired when it is deleted, we can't rely on its - // synchronization logic to make writes in thread A visible to a destructor - // running in thread B. - // - // Also note that the Acquire fence here could probably be replaced with an - // Acquire load, which could improve performance in highly-contended - // situations. See [2]. - // - // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - // [2]: (https://github.com/rust-lang/rust/pull/41714) - acquire!(self.inner().strong); - - // Make sure we aren't trying to "drop" the shared static for empty slices - // used by Default::default. - debug_assert!( - !ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner), - "Arcs backed by a static should never reach a strong count of 0. \ - Likely decrement_strong_count or from_raw were called too many times.", - ); - - // ignore-tidy-undocumented-unsafe - unsafe { - self.drop_slow(); - } - } -} - -impl Arc { - /// Attempts to downcast the `Arc` to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// use std::sync::Arc; - /// - /// fn print_if_string(value: Arc) { - /// if let Ok(string) = value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Arc::new(my_string)); - /// print_if_string(Arc::new(0i8)); - /// ``` - #[inline] - #[stable(feature = "rc_downcast", since = "1.29.0")] - pub fn downcast(self) -> Result, Self> - where - T: Any + Send + Sync, - { - if (*self).is::() { - // SAFETY: Check ensures the typecast is okay. - unsafe { - let (ptr, alloc) = Arc::into_inner_with_allocator(self); - Ok(Arc::from_inner_in(ptr.cast(), alloc)) - } - } else { - Err(self) - } - } - - /// Downcasts the `Arc` to a concrete type. - /// - /// For a safe alternative see [`downcast`]. - /// - /// # Examples - /// - /// ``` - /// #![feature(downcast_unchecked)] - /// - /// use std::any::Any; - /// use std::sync::Arc; - /// - /// let x: Arc = Arc::new(1_usize); - /// - /// unsafe { - /// assert_eq!(*x.downcast_unchecked::(), 1); - /// } - /// ``` - /// - /// # Safety - /// - /// The contained value must be of type `T`. Calling this method - /// with the incorrect type is *undefined behavior*. - /// - /// - /// [`downcast`]: Self::downcast - #[inline] - #[unstable(feature = "downcast_unchecked", issue = "90850")] - pub unsafe fn downcast_unchecked(self) -> Arc - where - T: Any + Send + Sync, - { - // SAFETY: Upheld by caller. - unsafe { - let (ptr, alloc) = Arc::into_inner_with_allocator(self); - Arc::from_inner_in(ptr.cast(), alloc) - } - } -} - -impl Weak { - /// Constructs a new `Weak`, without allocating any memory. - /// Calling [`upgrade`] on the return value always gives [`None`]. - /// - /// [`upgrade`]: Weak::upgrade - /// - /// # Examples - /// - /// ``` - /// use std::sync::Weak; - /// - /// let empty: Weak = Weak::new(); - /// assert!(empty.upgrade().is_none()); - /// ``` - #[inline] - #[stable(feature = "downgraded_weak", since = "1.10.0")] - #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] - #[must_use] - pub const fn new() -> Weak { - Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global } - } -} - -impl Weak { - /// Constructs a new `Weak`, without allocating any memory, technically in the provided - /// allocator. - /// Calling [`upgrade`] on the return value always gives [`None`]. - /// - /// [`upgrade`]: Weak::upgrade - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// - /// use std::sync::Weak; - /// use std::alloc::System; - /// - /// let empty: Weak = Weak::new_in(System); - /// assert!(empty.upgrade().is_none()); - /// ``` - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn new_in(alloc: A) -> Weak { - Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc } - } -} - -/// Helper type to allow accessing the reference counts without -/// making any assertions about the data field. -struct WeakInner<'a> { - weak: &'a Atomic, - strong: &'a Atomic, -} - -impl Weak { - /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. - /// - /// This can be used to safely get a strong reference (by calling [`upgrade`] - /// later) or to deallocate the weak count by dropping the `Weak`. - /// - /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], - /// as these don't own anything; the method still works on them). - /// - /// # Safety - /// - /// The pointer must have originated from the [`into_raw`] and must still own its potential - /// weak reference, and must point to a block of memory allocated by global allocator. - /// - /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this - /// takes ownership of one weak reference currently represented as a raw pointer (the weak - /// count is not modified by this operation) and therefore it must be paired with a previous - /// call to [`into_raw`]. - /// # Examples - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// let strong = Arc::new("hello".to_owned()); - /// - /// let raw_1 = Arc::downgrade(&strong).into_raw(); - /// let raw_2 = Arc::downgrade(&strong).into_raw(); - /// - /// assert_eq!(2, Arc::weak_count(&strong)); - /// - /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); - /// assert_eq!(1, Arc::weak_count(&strong)); - /// - /// drop(strong); - /// - /// // Decrement the last weak count. - /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); - /// ``` - /// - /// [`new`]: Weak::new - /// [`into_raw`]: Weak::into_raw - /// [`upgrade`]: Weak::upgrade - #[inline] - #[stable(feature = "weak_into_raw", since = "1.45.0")] - pub unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Upheld by caller. - unsafe { Weak::from_raw_in(ptr, Global) } - } - - /// Consumes the `Weak` and turns it into a raw pointer. - /// - /// This converts the weak pointer into a raw pointer, while still preserving the ownership of - /// one weak reference (the weak count is not modified by this operation). It can be turned - /// back into the `Weak` with [`from_raw`]. - /// - /// The same restrictions of accessing the target of the pointer as with - /// [`as_ptr`] apply. - /// - /// # Examples - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// let strong = Arc::new("hello".to_owned()); - /// let weak = Arc::downgrade(&strong); - /// let raw = weak.into_raw(); - /// - /// assert_eq!(1, Arc::weak_count(&strong)); - /// assert_eq!("hello", unsafe { &*raw }); - /// - /// drop(unsafe { Weak::from_raw(raw) }); - /// assert_eq!(0, Arc::weak_count(&strong)); - /// ``` - /// - /// [`from_raw`]: Weak::from_raw - /// [`as_ptr`]: Weak::as_ptr - #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "weak_into_raw", since = "1.45.0")] - pub fn into_raw(self) -> *const T { - ManuallyDrop::new(self).as_ptr() - } -} - -impl Weak { - /// Returns a reference to the underlying allocator. - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn allocator(&self) -> &A { - &self.alloc - } - - /// Returns a raw pointer to the object `T` pointed to by this `Weak`. - /// - /// The pointer is valid only if there are some strong references. The pointer may be dangling, - /// unaligned or even [`null`] otherwise. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// use std::ptr; - /// - /// let strong = Arc::new("hello".to_owned()); - /// let weak = Arc::downgrade(&strong); - /// // Both point to the same object - /// assert!(ptr::eq(&*strong, weak.as_ptr())); - /// // The strong here keeps it alive, so we can still access the object. - /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); - /// - /// drop(strong); - /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to - /// // undefined behavior. - /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); - /// ``` - /// - /// [`null`]: core::ptr::null "ptr::null" - #[must_use] - #[stable(feature = "weak_into_raw", since = "1.45.0")] - pub fn as_ptr(&self) -> *const T { - let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); - - if is_dangling(ptr) { - // If the pointer is dangling, we return the sentinel directly. This cannot be - // a valid payload address, as the payload is at least as aligned as ArcInner (usize). - ptr as *const T - } else { - // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. - // The payload may be dropped at this point, and we have to maintain provenance, - // so use raw pointer manipulation. - unsafe { &raw mut (*ptr).data } - } - } - - /// Consumes the `Weak`, returning the wrapped pointer and allocator. - /// - /// This converts the weak pointer into a raw pointer, while still preserving the ownership of - /// one weak reference (the weak count is not modified by this operation). It can be turned - /// back into the `Weak` with [`from_raw_in`]. - /// - /// The same restrictions of accessing the target of the pointer as with - /// [`as_ptr`] apply. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_ext)] - /// use std::sync::{Arc, Weak}; - /// use std::alloc::System; - /// - /// let strong = Arc::new_in("hello".to_owned(), System); - /// let weak = Arc::downgrade(&strong); - /// let (raw, alloc) = weak.into_raw_with_allocator(); - /// - /// assert_eq!(1, Arc::weak_count(&strong)); - /// assert_eq!("hello", unsafe { &*raw }); - /// - /// drop(unsafe { Weak::from_raw_in(raw, alloc) }); - /// assert_eq!(0, Arc::weak_count(&strong)); - /// ``` - /// - /// [`from_raw_in`]: Weak::from_raw_in - /// [`as_ptr`]: Weak::as_ptr - #[must_use = "losing the pointer will leak memory"] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub fn into_raw_with_allocator(self) -> (*const T, A) { - let this = mem::ManuallyDrop::new(self); - let result = this.as_ptr(); - // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped - let alloc = unsafe { ptr::read(&this.alloc) }; - (result, alloc) - } - - /// Converts a raw pointer previously created by [`into_raw`] back into `Weak` in the provided - /// allocator. - /// - /// This can be used to safely get a strong reference (by calling [`upgrade`] - /// later) or to deallocate the weak count by dropping the `Weak`. - /// - /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], - /// as these don't own anything; the method still works on them). - /// - /// # Safety - /// - /// The pointer must have originated from the [`into_raw`] and must still own its potential - /// weak reference, and must point to a block of memory allocated by `alloc`. - /// - /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this - /// takes ownership of one weak reference currently represented as a raw pointer (the weak - /// count is not modified by this operation) and therefore it must be paired with a previous - /// call to [`into_raw`]. - /// # Examples - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// let strong = Arc::new("hello".to_owned()); - /// - /// let raw_1 = Arc::downgrade(&strong).into_raw(); - /// let raw_2 = Arc::downgrade(&strong).into_raw(); - /// - /// assert_eq!(2, Arc::weak_count(&strong)); - /// - /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); - /// assert_eq!(1, Arc::weak_count(&strong)); - /// - /// drop(strong); - /// - /// // Decrement the last weak count. - /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); - /// ``` - /// - /// [`new`]: Weak::new - /// [`into_raw`]: Weak::into_raw - /// [`upgrade`]: Weak::upgrade - #[inline] - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] - pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { - // See Weak::as_ptr for context on how the input pointer is derived. - - let ptr = if is_dangling(ptr) { - // This is a dangling Weak. - ptr as *mut ArcInner - } else { - // Otherwise, we're guaranteed the pointer came from a nondangling Weak. - // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. - let offset = unsafe { data_offset(ptr) }; - // Thus, we reverse the offset to get the whole ArcInner. - // SAFETY: the pointer originated from a Weak, so this offset is safe. - unsafe { ptr.byte_sub(offset) as *mut ArcInner } - }; - - // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. - Weak { ptr: unsafe { NonNull::new_unchecked(ptr) }, alloc } - } -} - -impl Weak { - /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying - /// dropping of the inner value if successful. - /// - /// Returns [`None`] in the following cases: - /// - /// 1. The inner value has since been dropped or moved out. - /// - /// 2. This `Weak` does not point to an allocation. - /// - /// 3. The owning reference this `Weak` is associated with is either not fully-constructed or does not allow an upgrade. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// let weak_five = Arc::downgrade(&five); - /// - /// let strong_five: Option> = weak_five.upgrade(); - /// assert!(strong_five.is_some()); - /// - /// // Destroy all strong pointers. - /// drop(strong_five); - /// drop(five); - /// - /// assert!(weak_five.upgrade().is_none()); - /// ``` - #[must_use = "this returns a new `Arc`, \ - without modifying the original weak pointer"] - #[stable(feature = "arc_weak", since = "1.4.0")] - pub fn upgrade(&self) -> Option> - where - A: AllocatorClone, - { - #[inline] - fn checked_increment(n: usize) -> Option { - // Any write of 0 we can observe leaves the field in permanently zero state. - if n == 0 { - return None; - } - // See comments in `Arc::clone` for why we do this (for `mem::forget`). - if n > MAX_REFCOUNT { - panic_arc_overflow(); - } - Some(n + 1) - } - - // We use a CAS loop to increment the strong count instead of a - // fetch_add as this function should never take the reference count - // from zero to one. - // - // Relaxed is fine for the failure case because we don't have any expectations about the new state. - // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner - // value can be initialized after `Weak` references have already been created. In that case, we - // expect to observe the fully initialized value. - if self.inner()?.strong.try_update(Acquire, Relaxed, checked_increment).is_ok() { - // SAFETY: pointer is not null, verified in checked_increment - unsafe { Some(Arc::from_inner_in(self.ptr, self.alloc.clone())) } - } else { - None - } - } - - /// Gets the number of strong (`Arc`) pointers pointing to this allocation. - /// - /// If `self` was created using [`Weak::new`], this will return 0. - #[must_use] - #[stable(feature = "weak_counts", since = "1.41.0")] - pub fn strong_count(&self) -> usize { - if let Some(inner) = self.inner() { inner.strong.load(Relaxed) } else { 0 } - } - - /// Gets an approximation of the number of `Weak` pointers pointing to this - /// allocation. - /// - /// If `self` was created using [`Weak::new`], or if there are no remaining - /// strong pointers, this will return 0. - /// - /// # Accuracy - /// - /// Due to implementation details, the returned value can be off by 1 in - /// either direction when other threads are manipulating any `Arc`s or - /// `Weak`s pointing to the same allocation. - #[must_use] - #[stable(feature = "weak_counts", since = "1.41.0")] - pub fn weak_count(&self) -> usize { - if let Some(inner) = self.inner() { - let weak = inner.weak.load(Acquire); - let strong = inner.strong.load(Relaxed); - if strong == 0 { - 0 - } else { - // Since we observed that there was at least one strong pointer - // after reading the weak count, we know that the implicit weak - // reference (present whenever any strong references are alive) - // was still around when we observed the weak count, and can - // therefore safely subtract it. - weak - 1 - } - } else { - 0 - } - } - - /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, - /// (i.e., when this `Weak` was created by `Weak::new`). - #[inline] - fn inner(&self) -> Option> { - let ptr = self.ptr.as_ptr(); - if is_dangling(ptr) { - None - } else { - // We are careful to *not* create a reference covering the "data" field, as - // the field may be mutated concurrently (for example, if the last `Arc` - // is dropped, the data field will be dropped in-place). - // ignore-tidy-undocumented-unsafe - Some(unsafe { WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } }) - } - } - - /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if - /// both don't point to any allocation (because they were created with `Weak::new()`). However, - /// this function ignores the metadata of `dyn Trait` pointers. - /// - /// # Notes - /// - /// Since this compares pointers it means that `Weak::new()` will equal each - /// other, even though they don't point to any allocation. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let first_rc = Arc::new(5); - /// let first = Arc::downgrade(&first_rc); - /// let second = Arc::downgrade(&first_rc); - /// - /// assert!(first.ptr_eq(&second)); - /// - /// let third_rc = Arc::new(5); - /// let third = Arc::downgrade(&third_rc); - /// - /// assert!(!first.ptr_eq(&third)); - /// ``` - /// - /// Comparing `Weak::new`. - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// let first = Weak::new(); - /// let second = Weak::new(); - /// assert!(first.ptr_eq(&second)); - /// - /// let third_rc = Arc::new(()); - /// let third = Arc::downgrade(&third_rc); - /// assert!(!first.ptr_eq(&third)); - /// ``` - /// - /// [`ptr::eq`]: core::ptr::eq "ptr::eq" - #[inline] - #[must_use] - #[stable(feature = "weak_ptr_eq", since = "1.39.0")] - pub fn ptr_eq(&self, other: &Self) -> bool { - ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr()) - } -} - -#[stable(feature = "arc_weak", since = "1.4.0")] -impl Clone for Weak { - /// Makes a clone of the `Weak` pointer that points to the same allocation. - /// - /// # Examples - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// let weak_five = Arc::downgrade(&Arc::new(5)); - /// - /// let _ = Weak::clone(&weak_five); - /// ``` - #[inline] - fn clone(&self) -> Weak { - if let Some(inner) = self.inner() { - // See comments in Arc::clone() for why this is relaxed. This can use a - // fetch_add (ignoring the lock) because the weak count is only locked - // where are *no other* weak pointers in existence. (So we can't be - // running this code in that case). - let old_size = inner.weak.fetch_add(1, Relaxed); - - // See comments in Arc::clone() for why we do this (for mem::forget). - if old_size > MAX_REFCOUNT { - abort(); - } - } - - Weak { ptr: self.ptr, alloc: self.alloc.clone() } - } -} - -#[unstable(feature = "ergonomic_clones", issue = "132290")] -impl UseCloned for Weak {} - -#[stable(feature = "downgraded_weak", since = "1.10.0")] -impl Default for Weak { - /// Constructs a new `Weak`, without allocating memory. - /// Calling [`upgrade`] on the return value always - /// gives [`None`]. - /// - /// [`upgrade`]: Weak::upgrade - /// - /// # Examples - /// - /// ``` - /// use std::sync::Weak; - /// - /// let empty: Weak = Default::default(); - /// assert!(empty.upgrade().is_none()); - /// ``` - fn default() -> Weak { - Weak::new() - } -} - -#[stable(feature = "arc_weak", since = "1.4.0")] -unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak { - /// Drops the `Weak` pointer. - /// - /// # Examples - /// - /// ``` - /// use std::sync::{Arc, Weak}; - /// - /// struct Foo; - /// - /// impl Drop for Foo { - /// fn drop(&mut self) { - /// println!("dropped!"); - /// } - /// } - /// - /// let foo = Arc::new(Foo); - /// let weak_foo = Arc::downgrade(&foo); - /// let other_weak_foo = Weak::clone(&weak_foo); - /// - /// drop(weak_foo); // Doesn't print anything - /// drop(foo); // Prints "dropped!" - /// - /// assert!(other_weak_foo.upgrade().is_none()); - /// ``` - fn drop(&mut self) { - // If we find out that we were the last weak pointer, then its time to - // deallocate the data entirely. See the discussion in Arc::drop() about - // the memory orderings - // - // It's not necessary to check for the locked state here, because the - // weak count can only be locked if there was precisely one weak ref, - // meaning that drop could only subsequently run ON that remaining weak - // ref, which can only happen after the lock is released. - let inner = if let Some(inner) = self.inner() { inner } else { return }; - - if inner.weak.fetch_sub(1, Release) == 1 { - acquire!(inner.weak); - - // Make sure we aren't trying to "deallocate" the shared static for empty slices - // used by Default::default. - debug_assert!( - !ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner), - "Arc/Weaks backed by a static should never be deallocated. \ - Likely decrement_strong_count or from_raw were called too many times.", - ); - - // ignore-tidy-undocumented-unsafe - unsafe { - self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())) - } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -trait ArcEqIdent { - fn eq(&self, other: &Arc) -> bool; - fn ne(&self, other: &Arc) -> bool; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ArcEqIdent for Arc { - #[inline] - default fn eq(&self, other: &Arc) -> bool { - **self == **other - } - #[inline] - default fn ne(&self, other: &Arc) -> bool { - **self != **other - } -} - -/// We're doing this specialization here, and not as a more general optimization on `&T`, because it -/// would otherwise add a cost to all equality checks on refs. We assume that `Arc`s are used to -/// store large values, that are slow to clone, but also heavy to check for equality, causing this -/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to -/// the same value, than two `&T`s. -/// -/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. -#[stable(feature = "rust1", since = "1.0.0")] -impl ArcEqIdent for Arc { - #[inline] - fn eq(&self, other: &Arc) -> bool { - ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) || **self == **other - } - - #[inline] - fn ne(&self, other: &Arc) -> bool { - !ptr::eq(self.ptr.as_ptr(), other.ptr.as_ptr()) && **self != **other - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for Arc { - /// Equality for two `Arc`s. - /// - /// Two `Arc`s are equal if their inner values are equal, even if they are - /// stored in different allocation. - /// - /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Arc`s that point to the same allocation are always equal. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five == Arc::new(5)); - /// ``` - #[inline] - fn eq(&self, other: &Arc) -> bool { - ArcEqIdent::eq(self, other) - } - - /// Inequality for two `Arc`s. - /// - /// Two `Arc`s are not equal if their inner values are not equal. - /// - /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Arc`s that point to the same value are always equal. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five != Arc::new(6)); - /// ``` - #[inline] - fn ne(&self, other: &Arc) -> bool { - ArcEqIdent::ne(self, other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Arc { - /// Partial comparison for two `Arc`s. - /// - /// The two are compared by calling `partial_cmp()` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// use std::cmp::Ordering; - /// - /// let five = Arc::new(5); - /// - /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6))); - /// ``` - fn partial_cmp(&self, other: &Arc) -> Option { - (**self).partial_cmp(&**other) - } - - /// Less-than comparison for two `Arc`s. - /// - /// The two are compared by calling `<` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five < Arc::new(6)); - /// ``` - fn lt(&self, other: &Arc) -> bool { - *(*self) < *(*other) - } - - /// 'Less than or equal to' comparison for two `Arc`s. - /// - /// The two are compared by calling `<=` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five <= Arc::new(5)); - /// ``` - fn le(&self, other: &Arc) -> bool { - *(*self) <= *(*other) - } - - /// Greater-than comparison for two `Arc`s. - /// - /// The two are compared by calling `>` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five > Arc::new(4)); - /// ``` - fn gt(&self, other: &Arc) -> bool { - *(*self) > *(*other) - } - - /// 'Greater than or equal to' comparison for two `Arc`s. - /// - /// The two are compared by calling `>=` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five >= Arc::new(5)); - /// ``` - fn ge(&self, other: &Arc) -> bool { - *(*self) >= *(*other) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Arc { - /// Comparison for two `Arc`s. - /// - /// The two are compared by calling `cmp()` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// use std::cmp::Ordering; - /// - /// let five = Arc::new(5); - /// - /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6))); - /// ``` - fn cmp(&self, other: &Arc) -> Ordering { - (**self).cmp(&**other) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Arc {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for Arc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Arc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Pointer for Arc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&(&raw const **self), f) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for Arc { - /// Creates a new `Arc`, with the `Default` value for `T`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x: Arc = Default::default(); - /// assert_eq!(*x, 0); - /// ``` - fn default() -> Arc { - // ignore-tidy-undocumented-unsafe - unsafe { - Self::from_inner(Box::into_non_null(Box::write( - Box::new_uninit(), - ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data: T::default(), - }, - ))) - } - } -} - -/// Struct to hold the static `ArcInner` used for empty `Arc` as -/// returned by `Default::default`. -/// -/// Layout notes: -/// * `repr(align(16))` so we can use it for `[T]` with `align_of::() <= 16`. -/// * `repr(C)` so `inner` is at offset 0 (and thus guaranteed to actually be aligned to 16). -/// * `[u8; 1]` (to be initialized with 0) so it can be used for `Arc`. -#[repr(C, align(16))] -struct SliceArcInnerForStatic { - inner: ArcInner<[u8; 1]>, -} -#[cfg(not(no_global_oom_handling))] -const MAX_STATIC_INNER_SLICE_ALIGNMENT: usize = 16; - -static STATIC_INNER_SLICE: SliceArcInnerForStatic = SliceArcInnerForStatic { - inner: ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data: [0], - }, -}; - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "more_rc_default_impls", since = "1.80.0")] -impl Default for Arc { - /// Creates an empty str inside an Arc - /// - /// This may or may not share an allocation with other Arcs. - #[inline] - fn default() -> Self { - let arc: Arc<[u8]> = Default::default(); - debug_assert!(core::str::from_utf8(&arc).is_ok()); - let (ptr, alloc) = Arc::into_inner_with_allocator(arc); - // ignore-tidy-undocumented-unsafe - unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner, alloc) } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "more_rc_default_impls", since = "1.80.0")] -impl Default for Arc { - /// Creates an empty CStr inside an Arc - /// - /// This may or may not share an allocation with other Arcs. - #[inline] - fn default() -> Self { - use core::ffi::CStr; - let inner: NonNull> = NonNull::from(&STATIC_INNER_SLICE.inner); - let inner: NonNull> = - NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); - // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. - let this: mem::ManuallyDrop> = - // ignore-tidy-undocumented-unsafe - unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; - (*this).clone() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "more_rc_default_impls", since = "1.80.0")] -impl Default for Arc<[T]> { - /// Creates an empty `[T]` inside an Arc - /// - /// This may or may not share an allocation with other Arcs. - #[inline] - fn default() -> Self { - if align_of::() <= MAX_STATIC_INNER_SLICE_ALIGNMENT { - // We take a reference to the whole struct instead of the ArcInner<[u8; 1]> inside it so - // we don't shrink the range of bytes the ptr is allowed to access under Stacked Borrows. - // (Miri complains on 32-bit targets with Arc<[Align16]> otherwise.) - // (Note that NonNull::from(&STATIC_INNER_SLICE.inner) is fine under Tree Borrows.) - let inner: NonNull = NonNull::from(&STATIC_INNER_SLICE); - let inner: NonNull> = inner.cast(); - // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. - let this: mem::ManuallyDrop> = - // ignore-tidy-undocumented-unsafe - unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; - return (*this).clone(); - } - - // If T's alignment is too large for the static, make a new unique allocation. - let arr: [T; 0] = []; - Arc::from(arr) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "pin_default_impls", since = "1.91.0")] -impl Default for Pin> -where - T: ?Sized, - Arc: Default, -{ - #[inline] - fn default() -> Self { - // SAFETY: We own and create the pinned pointer. - unsafe { Pin::new_unchecked(Arc::::default()) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Hash for Arc { - fn hash(&self, state: &mut H) { - (**self).hash(state) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "from_for_ptrs", since = "1.6.0")] -impl From for Arc { - /// Converts a `T` into an `Arc` - /// - /// The conversion moves the value into a - /// newly allocated `Arc`. It is equivalent to - /// calling `Arc::new(t)`. - /// - /// # Example - /// ```rust - /// # use std::sync::Arc; - /// let x = 5; - /// let arc = Arc::new(5); - /// - /// assert_eq!(Arc::from(x), arc); - /// ``` - fn from(t: T) -> Self { - Arc::new(t) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_array", since = "1.74.0")] -impl From<[T; N]> for Arc<[T]> { - /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. - /// - /// The conversion moves the array into a newly allocated `Arc`. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let original: [i32; 3] = [1, 2, 3]; - /// let shared: Arc<[i32]> = Arc::from(original); - /// assert_eq!(&[1, 2, 3], &shared[..]); - /// ``` - #[inline] - fn from(v: [T; N]) -> Arc<[T]> { - Arc::<[T; N]>::from(v) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From<&[T]> for Arc<[T]> { - /// Allocates a reference-counted slice and fills it by cloning `v`'s items. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let original: &[i32] = &[1, 2, 3]; - /// let shared: Arc<[i32]> = Arc::from(original); - /// assert_eq!(&[1, 2, 3], &shared[..]); - /// ``` - #[inline] - fn from(v: &[T]) -> Arc<[T]> { - >::from_slice(v) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] -impl From<&mut [T]> for Arc<[T]> { - /// Allocates a reference-counted slice and fills it by cloning `v`'s items. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let mut original = [1, 2, 3]; - /// let original: &mut [i32] = &mut original; - /// let shared: Arc<[i32]> = Arc::from(original); - /// assert_eq!(&[1, 2, 3], &shared[..]); - /// ``` - #[inline] - fn from(v: &mut [T]) -> Arc<[T]> { - Arc::from(&*v) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From<&str> for Arc { - /// Allocates a reference-counted `str` and copies `v` into it. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let shared: Arc = Arc::from("eggplant"); - /// assert_eq!("eggplant", &shared[..]); - /// ``` - #[inline] - fn from(v: &str) -> Arc { - let arc = Arc::<[u8]>::from(v.as_bytes()); - // ignore-tidy-undocumented-unsafe - unsafe { Arc::from_raw(Arc::into_raw(arc) as *const str) } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] -impl From<&mut str> for Arc { - /// Allocates a reference-counted `str` and copies `v` into it. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let mut original = String::from("eggplant"); - /// let original: &mut str = &mut original; - /// let shared: Arc = Arc::from(original); - /// assert_eq!("eggplant", &shared[..]); - /// ``` - #[inline] - fn from(v: &mut str) -> Arc { - Arc::from(&*v) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From for Arc { - /// Allocates a reference-counted `str` and copies `v` into it. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let unique: String = "eggplant".to_owned(); - /// let shared: Arc = Arc::from(unique); - /// assert_eq!("eggplant", &shared[..]); - /// ``` - #[inline] - fn from(v: String) -> Arc { - Arc::from(&v[..]) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Arc { - /// Move a boxed object to a new, reference-counted allocation. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let unique: Box = Box::from("eggplant"); - /// let shared: Arc = Arc::from(unique); - /// assert_eq!("eggplant", &shared[..]); - /// ``` - #[inline] - fn from(v: Box) -> Arc { - Arc::from_box_in(v) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Arc<[T], A> { - /// Allocates a reference-counted slice and moves `v`'s items into it. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let unique: Vec = vec![1, 2, 3]; - /// let shared: Arc<[i32]> = Arc::from(unique); - /// assert_eq!(&[1, 2, 3], &shared[..]); - /// ``` - #[inline] - fn from(v: Vec) -> Arc<[T], A> { - // ignore-tidy-undocumented-unsafe - unsafe { - let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_allocator(); - - let rc_ptr = Self::allocate_for_slice_in(len, &alloc); - ptr::copy_nonoverlapping(vec_ptr, (&raw mut (*rc_ptr).data) as *mut T, len); - - // Create a `Vec` with length 0, to deallocate the buffer - // without dropping its contents or the allocator - let _ = Vec::from_raw_parts_in(vec_ptr, 0, cap, &alloc); - - Self::from_ptr_in(rc_ptr, alloc) - } - } -} - -#[stable(feature = "shared_from_cow", since = "1.45.0")] -impl<'a, B> From> for Arc -where - B: ToOwned + ?Sized, - Arc: From<&'a B> + From, -{ - /// Creates an atomically reference-counted pointer from a clone-on-write - /// pointer by copying its content. - /// - /// # Example - /// - /// ```rust - /// # use std::sync::Arc; - /// # use std::borrow::Cow; - /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); - /// let shared: Arc = Arc::from(cow); - /// assert_eq!("eggplant", &shared[..]); - /// ``` - #[inline] - fn from(cow: Cow<'a, B>) -> Arc { - match cow { - Cow::Borrowed(s) => Arc::from(s), - Cow::Owned(s) => Arc::from(s), - } - } -} - -#[stable(feature = "shared_from_str", since = "1.62.0")] -impl From> for Arc<[u8]> { - /// Converts an atomically reference-counted string slice into a byte slice. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// let string: Arc = Arc::from("eggplant"); - /// let bytes: Arc<[u8]> = Arc::from(string); - /// assert_eq!("eggplant".as_bytes(), bytes.as_ref()); - /// ``` - #[inline] - fn from(rc: Arc) -> Self { - // SAFETY: `str` has the same layout as `[u8]`. - unsafe { Arc::from_raw(Arc::into_raw(rc) as *const [u8]) } - } -} - -#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Arc<[T; N], A> { - type Error = Arc<[T], A>; - - fn try_from(boxed_slice: Arc<[T], A>) -> Result { - if boxed_slice.len() == N { - let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice); - // ignore-tidy-undocumented-unsafe - Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) - } else { - Err(boxed_slice) - } - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_iter", since = "1.37.0")] -impl FromIterator for Arc<[T]> { - /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. - /// - /// # Performance characteristics - /// - /// ## The general case - /// - /// In the general case, collecting into `Arc<[T]>` is done by first - /// collecting into a `Vec`. That is, when writing the following: - /// - /// ```rust - /// # use std::sync::Arc; - /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); - /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); - /// ``` - /// - /// this behaves as if we wrote: - /// - /// ```rust - /// # use std::sync::Arc; - /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0) - /// .collect::>() // The first set of allocations happens here. - /// .into(); // A second allocation for `Arc<[T]>` happens here. - /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); - /// ``` - /// - /// This will allocate as many times as needed for constructing the `Vec` - /// and then it will allocate once for turning the `Vec` into the `Arc<[T]>`. - /// - /// ## Iterators of known length - /// - /// When your `Iterator` implements `TrustedLen` and is of an exact size, - /// a single allocation will be made for the `Arc<[T]>`. For example: - /// - /// ```rust - /// # use std::sync::Arc; - /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here. - /// # assert_eq!(&*evens, &*(0..10).collect::>()); - /// ``` - fn from_iter>(iter: I) -> Self { - ToArcSlice::to_arc_slice(iter.into_iter()) - } -} - -#[cfg(not(no_global_oom_handling))] -/// Specialization trait used for collecting into `Arc<[T]>`. -trait ToArcSlice: Iterator + Sized { - fn to_arc_slice(self) -> Arc<[T]>; -} - -#[cfg(not(no_global_oom_handling))] -impl> ToArcSlice for I { - default fn to_arc_slice(self) -> Arc<[T]> { - self.collect::>().into() - } -} - -#[cfg(not(no_global_oom_handling))] -impl> ToArcSlice for I { - fn to_arc_slice(self) -> Arc<[T]> { - // This is the case for a `TrustedLen` iterator. - let (low, high) = self.size_hint(); - if let Some(high) = high { - debug_assert_eq!( - low, - high, - "TrustedLen iterator's size hint is not exact: {:?}", - (low, high) - ); - - // SAFETY: We need to ensure that the iterator has an exact length and we have. - unsafe { Arc::from_iter_exact(self, low) } - } else { - // TrustedLen contract guarantees that `upper_bound == None` implies an iterator - // length exceeding `usize::MAX`. - // The default implementation would collect into a vec which would panic. - // Thus we panic here immediately without invoking `Vec` code. - panic!("capacity overflow"); - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl borrow::Borrow for Arc { - fn borrow(&self) -> &T { - self - } -} - -#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl AsRef for Arc { - fn as_ref(&self) -> &T { - self - } -} - -#[stable(feature = "pin", since = "1.33.0")] -impl Unpin for Arc {} - -/// Gets the offset within an `ArcInner` for the payload behind a pointer. -/// -/// # Safety -/// -/// The pointer must point to (and have valid metadata for) a previously -/// valid instance of T, but the T is allowed to be dropped. -unsafe fn data_offset(ptr: *const T) -> usize { - // Align the unsized value to the end of the ArcInner. - // Because ArcInner is repr(C), it will always be the last field in memory. - // SAFETY: since the only unsized types possible are slices, trait objects, - // and extern types, the input safety requirement is currently enough to - // satisfy the requirements of Alignment::of_val_raw; this is an implementation - // detail of the language that must not be relied upon outside of std. - unsafe { data_offset_alignment(Alignment::of_val_raw(ptr)) } -} - -#[inline] -fn data_offset_alignment(alignment: Alignment) -> usize { - let layout = Layout::new::>(); - layout.size() + layout.padding_needed_for(alignment) -} - -/// A unique owning pointer to an [`ArcInner`] **that does not imply the contents are initialized,** -/// but will deallocate it (without dropping the value) when dropped. -/// -/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic. -struct UniqueArcUninit { - ptr: NonNull>, - layout_for_value: Layout, - alloc: Option, -} - -impl UniqueArcUninit { - /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it. - #[cfg(not(no_global_oom_handling))] - fn new(for_value: &T, alloc: A) -> UniqueArcUninit { - let layout = Layout::for_value(for_value); - // ignore-tidy-undocumented-unsafe - let ptr = unsafe { - Arc::allocate_for_layout( - layout, - |layout_for_arcinner| alloc.allocate(layout_for_arcinner), - |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner), - ) - }; - Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } - } - - /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it, - /// returning an error if allocation fails. - fn try_new(for_value: &T, alloc: A) -> Result, AllocError> { - let layout = Layout::for_value(for_value); - // ignore-tidy-undocumented-unsafe - let ptr = unsafe { - Arc::try_allocate_for_layout( - layout, - |layout_for_arcinner| alloc.allocate(layout_for_arcinner), - |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner), - )? - }; - Ok(Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }) - } - - /// Returns the pointer to be written into to initialize the [`Arc`]. - fn data_ptr(&mut self) -> *mut T { - let offset = data_offset_alignment(self.layout_for_value.alignment()); - // ignore-tidy-undocumented-unsafe - unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } - } - - /// Upgrade this into a normal [`Arc`]. - /// - /// # Safety - /// - /// The data must have been initialized (by writing to [`Self::data_ptr()`]). - unsafe fn into_arc(self) -> Arc { - let mut this = ManuallyDrop::new(self); - let ptr = this.ptr.as_ptr(); - let alloc = this.alloc.take().unwrap(); - - // SAFETY: The pointer is valid as per `UniqueArcUninit::new`, and the caller is responsible - // for having initialized the data. - unsafe { Arc::from_ptr_in(ptr, alloc) } - } -} - -impl Drop for UniqueArcUninit { - fn drop(&mut self) { - // SAFETY: - // * new() produced a pointer safe to deallocate. - // * We own the pointer unless into_arc() was called, which forgets us. - unsafe { - self.alloc.take().unwrap().deallocate( - self.ptr.cast(), - arcinner_layout_for_value_layout(self.layout_for_value), - ); - } - } -} - -#[stable(feature = "arc_error", since = "1.52.0")] -impl core::error::Error for Arc { - #[allow(deprecated)] - fn cause(&self) -> Option<&dyn core::error::Error> { - core::error::Error::cause(&**self) - } - - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - core::error::Error::source(&**self) - } - - fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) { - core::error::Error::provide(&**self, req); - } -} - -/// A uniquely owned [`Arc`]. -/// -/// This represents an `Arc` that is known to be uniquely owned -- that is, have exactly one strong -/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong -/// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`. -/// -/// Because it is uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common -/// use case is to have an object be mutable during its initialization phase but then have it become -/// immutable and converted to a normal `Arc`. -/// -/// This can be used as a flexible way to create cyclic data structures, as in the example below. -/// -/// ``` -/// #![feature(unique_rc_arc)] -/// use std::sync::{Arc, Weak, UniqueArc}; -/// -/// struct Gadget { -/// me: Weak, -/// } -/// -/// fn create_gadget() -> Option> { -/// let mut rc = UniqueArc::new(Gadget { -/// me: Weak::new(), -/// }); -/// rc.me = UniqueArc::downgrade(&rc); -/// Some(UniqueArc::into_arc(rc)) -/// } -/// -/// create_gadget().unwrap(); -/// ``` -/// -/// An advantage of using `UniqueArc` over [`Arc::new_cyclic`] to build cyclic data structures is that -/// [`Arc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the -/// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data, -/// including fallible or async constructors. -#[unstable(feature = "unique_rc_arc", issue = "112566")] -pub struct UniqueArc< - T: ?Sized, - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, -> { - ptr: NonNull>, - // Define the ownership of `ArcInner` for drop-check - _marker: PhantomData>, - // Invariance is necessary for soundness: once other `Weak` - // references exist, we already have a form of shared mutability! - _marker2: PhantomData<*mut T>, - alloc: A, -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -unsafe impl Send for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -unsafe impl Sync for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -// #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: ?Sized, A: Allocator> CoerceUnsized> - for UniqueArc -{ -} - -//#[unstable(feature = "unique_rc_arc", issue = "112566")] -#[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: ?Sized> DispatchFromDyn> for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl fmt::Display for UniqueArc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl fmt::Debug for UniqueArc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl fmt::Pointer for UniqueArc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&(&raw const **self), f) - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl borrow::Borrow for UniqueArc { - fn borrow(&self) -> &T { - self - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl borrow::BorrowMut for UniqueArc { - fn borrow_mut(&mut self) -> &mut T { - self - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl AsRef for UniqueArc { - fn as_ref(&self) -> &T { - self - } -} - #[unstable(feature = "unique_rc_arc", issue = "112566")] -impl AsMut for UniqueArc { - fn as_mut(&mut self) -> &mut T { - self - } -} - -#[cfg(not(no_global_oom_handling))] -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl From for UniqueArc { - #[inline(always)] - fn from(value: T) -> Self { - Self::new(value) - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl Unpin for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl PartialEq for UniqueArc { - /// Equality for two `UniqueArc`s. - /// - /// Two `UniqueArc`s are equal if their inner values are equal. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// - /// let five = UniqueArc::new(5); - /// - /// assert!(five == UniqueArc::new(5)); - /// ``` - #[inline] - fn eq(&self, other: &Self) -> bool { - PartialEq::eq(&**self, &**other) - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl PartialOrd for UniqueArc { - /// Partial comparison for two `UniqueArc`s. - /// - /// The two are compared by calling `partial_cmp()` on their inner values. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// use std::cmp::Ordering; - /// - /// let five = UniqueArc::new(5); - /// - /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6))); - /// ``` - #[inline(always)] - fn partial_cmp(&self, other: &UniqueArc) -> Option { - (**self).partial_cmp(&**other) - } - - /// Less-than comparison for two `UniqueArc`s. - /// - /// The two are compared by calling `<` on their inner values. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// - /// let five = UniqueArc::new(5); - /// - /// assert!(five < UniqueArc::new(6)); - /// ``` - #[inline(always)] - fn lt(&self, other: &UniqueArc) -> bool { - **self < **other - } - - /// 'Less than or equal to' comparison for two `UniqueArc`s. - /// - /// The two are compared by calling `<=` on their inner values. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// - /// let five = UniqueArc::new(5); - /// - /// assert!(five <= UniqueArc::new(5)); - /// ``` - #[inline(always)] - fn le(&self, other: &UniqueArc) -> bool { - **self <= **other - } - - /// Greater-than comparison for two `UniqueArc`s. - /// - /// The two are compared by calling `>` on their inner values. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// - /// let five = UniqueArc::new(5); - /// - /// assert!(five > UniqueArc::new(4)); - /// ``` - #[inline(always)] - fn gt(&self, other: &UniqueArc) -> bool { - **self > **other - } - - /// 'Greater than or equal to' comparison for two `UniqueArc`s. - /// - /// The two are compared by calling `>=` on their inner values. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// - /// let five = UniqueArc::new(5); - /// - /// assert!(five >= UniqueArc::new(5)); - /// ``` - #[inline(always)] - fn ge(&self, other: &UniqueArc) -> bool { - **self >= **other - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl Ord for UniqueArc { - /// Comparison for two `UniqueArc`s. - /// - /// The two are compared by calling `cmp()` on their inner values. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// use std::cmp::Ordering; - /// - /// let five = UniqueArc::new(5); - /// - /// assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6))); - /// ``` - #[inline] - fn cmp(&self, other: &UniqueArc) -> Ordering { - (**self).cmp(&**other) - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl Eq for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl Hash for UniqueArc { - fn hash(&self, state: &mut H) { - (**self).hash(state); - } -} - -impl UniqueArc { - /// Creates a new `UniqueArc`. - /// - /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading - /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`]. - /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will - /// point to the new [`Arc`]. - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] - pub fn new(value: T) -> Self { - Self::new_in(value, Global) - } - - /// Like [`new`](Self::new), but returns an error if the allocation - /// fails, instead of calling [`handle_alloc_error`]. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - pub fn try_new(value: T) -> Result { - Self::try_new_in(value, Global) - } -} - -impl UniqueArc { - /// Creates a new `UniqueArc` in the provided allocator. - /// - /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading - /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`]. - /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will - /// point to the new [`Arc`]. - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "163177")] - #[must_use] - pub fn new_in(data: T, alloc: A) -> Self { - let (ptr, alloc) = Box::into_non_null_with_allocator(Box::new_in( - ArcInner { - strong: atomic::AtomicUsize::new(0), - // keep one weak reference so if all the weak pointers that are created are dropped - // the UniqueArc still stays valid. - weak: atomic::AtomicUsize::new(1), - data, - }, - alloc, - )); - Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc } - } - - /// Like [`new_in`](Self::new_in), but returns an error if the allocation - /// fails, instead of calling [`handle_alloc_error`]. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "163177")] - pub fn try_new_in(data: T, alloc: A) -> Result { - let (ptr, alloc) = Box::into_non_null_with_allocator(Box::try_new_in( - ArcInner { - strong: atomic::AtomicUsize::new(0), - // keep one weak reference so if all the weak pointers that are created are dropped - // the UniqueArc still stays valid. - weak: atomic::AtomicUsize::new(1), - data, - }, - alloc, - )?); - Ok(Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc }) - } - - /// Consumes the `UniqueArc`, returning its wrapped value and allocator. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - // #[unstable(feature = "allocator_api", issue = "163177")] - #[must_use] - pub fn unwrap_with_allocator(this: Self) -> (T, A) { - let inner_ptr = this.ptr; - let (data_ptr, alloc) = Self::into_raw_with_allocator(this); - - // SAFETY: Conceptually moves out of the `UniqueRc`. - // We do not use the data inside ever again. - let val = unsafe { data_ptr.read() }; - - // Drop the strong-weak ref - drop(Weak { ptr: inner_ptr, alloc: &alloc }); - - (val, alloc) - } - - /// Consumes the `UniqueArc`, returning its wrapped value. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] - pub fn unwrap(this: Self) -> T { - Self::unwrap_with_allocator(this).0 - } - - /// Maps the value in a `UniqueArc`, reusing the allocation if possible. - /// - /// `f` is called on a reference to the value in the `UniqueArc`, and the result is returned, - /// also in a `UniqueArc`. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `UniqueArc::map(u, f)` instead of `u.map(f)`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// - /// use std::sync::UniqueArc; - /// - /// let r = UniqueArc::new(7); - /// let new = UniqueArc::map(r, |i| i + 7); - /// assert_eq!(*new, 14); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "unique_rc_arc", issue = "112566")] - pub fn map(this: Self, f: impl FnOnce(T) -> U) -> UniqueArc { - if size_of::() == size_of::() - && align_of::() == align_of::() - && UniqueArc::weak_count(&this) == 0 - { - // ignore-tidy-undocumented-unsafe - unsafe { - let (ptr, alloc) = UniqueArc::into_raw_with_allocator(this); - let value = ptr.read(); - let allocation = - UniqueArc::from_raw_with_allocator(ptr.cast::>(), alloc); - - UniqueArc::write(allocation, f(value)) - } - } else { - let (val, alloc) = UniqueArc::unwrap_with_allocator(this); - UniqueArc::new_in(f(val), alloc) - } - } - - /// Attempts to map the value in a `UniqueArc`, reusing the allocation if possible. - /// - /// `f` is called on a reference to the value in the `UniqueArc`, and if the operation succeeds, - /// the result is returned, also in a `UniqueArc`. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `UniqueArc::try_map(u, f)` instead of `u.try_map(f)`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// # Examples - /// - /// ``` - /// #![feature(smart_pointer_try_map)] - /// #![feature(unique_rc_arc)] - /// - /// use std::sync::UniqueArc; - /// - /// let b = UniqueArc::new(7); - /// let new = UniqueArc::try_map(b, u32::try_from).unwrap(); - /// assert_eq!(*new, 7); - /// ``` - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "smart_pointer_try_map", issue = "144419")] - pub fn try_map( - this: Self, - f: impl FnOnce(T) -> R, - ) -> >>::TryType - where - R: Try, - R::Residual: Residual>, - { - if size_of::() == size_of::() - && align_of::() == align_of::() - && UniqueArc::weak_count(&this) == 0 - { - // ignore-tidy-undocumented-unsafe - unsafe { - let (ptr, alloc) = UniqueArc::into_raw_with_allocator(this); - let value = ptr.read(); - let allocation = UniqueArc::from_raw_with_allocator( - ptr.cast::>(), - alloc, - ); - - try { UniqueArc::write(allocation, f(value)?) } - } - } else { - let (val, alloc) = UniqueArc::unwrap_with_allocator(this); - try { UniqueArc::new_in(f(val)?, alloc) } - } - } -} - -impl UniqueArc { - #[cfg(not(no_global_oom_handling))] - unsafe fn from_raw_with_allocator(ptr: *const T, alloc: A) -> Self { - // SAFETY: Upheld by caller. - let offset = unsafe { data_offset(ptr) }; - - // Reverse the offset to find the original ArcInner. - // SAFETY: Upheld by caller. - let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut ArcInner }; - - Self { - // SAFETY: Upheld by caller. - ptr: unsafe { NonNull::new_unchecked(rc_ptr) }, - _marker: PhantomData, - _marker2: PhantomData, - alloc, - } - } - - fn into_raw_with_allocator(this: Self) -> (*const T, A) { - let this = ManuallyDrop::new(this); - // SAFETY: The copy of the allocator stored in `this` is forgotten - (Self::as_ptr(&*this), unsafe { ptr::read(&this.alloc) }) - } - - /// Converts the `UniqueArc` into a regular [`Arc`]. - /// - /// This consumes the `UniqueArc` and returns a regular [`Arc`] that contains the `value` that - /// is passed to `into_arc`. - /// - /// Any weak references created before this method is called can now be upgraded to strong - /// references. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] - pub fn into_arc(this: Self) -> Arc { - let this = ManuallyDrop::new(this); - - // Move the allocator out. - // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in - // a `ManuallyDrop`. - let alloc: A = unsafe { ptr::read(&this.alloc) }; - - // SAFETY: This pointer was allocated at creation time so we know it is valid. - unsafe { - // Convert our weak reference into a strong reference - (*this.ptr.as_ptr()).strong.store(1, Release); - Arc::from_inner_in(this.ptr, alloc) - } - } - - #[cfg(not(no_global_oom_handling))] - fn weak_count(this: &Self) -> usize { - this.inner().weak.load(Acquire) - 1 - } - - #[cfg(not(no_global_oom_handling))] - fn inner(&self) -> &ArcInner { - // SAFETY: while this UniqueArc is alive we're guaranteed that the inner pointer is valid. - unsafe { self.ptr.as_ref() } - } - - fn as_ptr(this: &Self) -> *const T { - let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); - - // SAFETY: This cannot go through Deref::deref or UniqueArc::inner because - // this is required to retain raw/mut provenance such that e.g. `get_mut` can - // write through the pointer after the Rc is recovered through `from_raw`. - unsafe { &raw mut (*ptr).data } - } - - #[inline] - fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { - let this = mem::ManuallyDrop::new(this); - // SAFETY: Pointer is valid for reads and only read once. - (this.ptr, unsafe { ptr::read(&this.alloc) }) - } - - #[inline] - unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { - Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc } - } -} - -impl UniqueArc { - /// Creates a new weak reference to the `UniqueArc`. - /// - /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted - /// to a [`Arc`] using [`UniqueArc::into_arc`]. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] - pub fn downgrade(this: &Self) -> Weak { - // Using a relaxed ordering is alright here, as knowledge of the - // original reference prevents other threads from erroneously deleting - // the object or converting the object to a normal `Arc`. - // - // Note that we don't need to test if the weak counter is locked because there - // are no such operations like `Arc::get_mut` or `Arc::make_mut` that will lock - // the weak counter. - // - // SAFETY: This pointer was allocated at creation time so we know it is valid. - let old_size = unsafe { (*this.ptr.as_ptr()).weak.fetch_add(1, Relaxed) }; - - // See comments in Arc::clone() for why we do this (for mem::forget). - if old_size > MAX_REFCOUNT { - abort(); - } - - Weak { ptr: this.ptr, alloc: this.alloc.clone() } - } -} - -impl UniqueArc, A> { - /// Writes the value and converts to `UniqueArc`. - /// - /// This method converts similarly to [`assume_init`](Self::assume_init) but - /// writes `value` into it before conversion, thus guaranteeing safety. - #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] - pub fn write(mut this: Self, value: T) -> UniqueArc { - // SAFETY: Writing initialises the wrapped value. - unsafe { - this.write(value); - this.assume_init() - } - } - - /// Converts to `UniqueArc`. - /// - /// # Safety - /// - /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the value - /// really is in an initialized state. - /// Calling this when the content is not yet fully initialized - /// causes immediate undefined behavior. - /// - /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init - #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] - pub unsafe fn assume_init(self) -> UniqueArc { - let (ptr, alloc) = UniqueArc::into_inner_with_allocator(self); - // SAFETY: Upheld by caller. - unsafe { UniqueArc::from_inner_in(ptr.cast(), alloc) } - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl Deref for UniqueArc { - type Target = T; - - fn deref(&self) -> &T { - // SAFETY: This pointer was allocated at creation time so we know it is valid. - unsafe { &self.ptr.as_ref().data } - } -} - -// #[unstable(feature = "unique_rc_arc", issue = "112566")] -#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinSafePointer for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -impl DerefMut for UniqueArc { - fn deref_mut(&mut self) -> &mut T { - // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we - // have unique ownership and therefore it's safe to make a mutable reference because - // `UniqueArc` owns the only strong reference to itself. - // We also need to be careful to only create a mutable reference to the `data` field, - // as a mutable reference to the entire `ArcInner` would assert uniqueness over the - // ref count fields too, invalidating any attempt by `Weak`s to access the ref count. - unsafe { &mut (*self.ptr.as_ptr()).data } - } -} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -// #[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl DerefPure for UniqueArc {} - -#[unstable(feature = "unique_rc_arc", issue = "112566")] -unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { - fn drop(&mut self) { - // See `Arc::drop_slow` which drops an `Arc` with a strong count of 0. - // SAFETY: This pointer was allocated at creation time so we know it is valid. - let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; - - // ignore-tidy-undocumented-unsafe - unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; - } -} - -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] -unsafe impl Allocator for Arc { - #[inline] - fn allocate(&self, layout: Layout) -> Result, AllocError> { - (**self).allocate(layout) - } - - #[inline] - fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { - (**self).allocate_zeroed(layout) - } - - #[inline] - unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { - // SAFETY: the safety contract must be upheld by the caller - unsafe { (**self).deallocate(ptr, layout) } - } - - #[inline] - unsafe fn grow( - &self, - ptr: NonNull, - old_layout: Layout, - new_layout: Layout, - ) -> Result, AllocError> { - // SAFETY: the safety contract must be upheld by the caller - unsafe { (**self).grow(ptr, old_layout, new_layout) } - } - - #[inline] - unsafe fn grow_zeroed( - &self, - ptr: NonNull, - old_layout: Layout, - new_layout: Layout, - ) -> Result, AllocError> { - // SAFETY: the safety contract must be upheld by the caller - unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) } - } - - #[inline] - unsafe fn shrink( - &self, - ptr: NonNull, - old_layout: Layout, - new_layout: Layout, - ) -> Result, AllocError> { - // SAFETY: the safety contract must be upheld by the caller - unsafe { (**self).shrink(ptr, old_layout, new_layout) } - } -} - -#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] -unsafe impl AllocatorClone for Arc {} +pub use crate::rcs::arc::UniqueArc; +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::rcs::arc::{Arc, Weak}; diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 76550081a703c..a5f46099173c0 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -50,7 +50,6 @@ #![feature(trusted_random_access)] #![feature(try_reserve_kind)] #![feature(try_trait_v2)] -#![feature(unwrap_infallible)] #![feature(wtf8_internals)] // tidy-alphabetical-end // diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ecc8b66ec5785..96999f154c42f 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2133,7 +2133,7 @@ pub const unsafe fn unchecked_mul(x: T, y: T) -> T; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[rustc_allow_const_fn_unstable(const_trait_impl)] #[miri::intrinsic_fallback_is_spec] pub const fn rotate_left(x: T, shift: u32) -> T { // Make sure to call the intrinsic for `funnel_shl`, not the fallback impl. @@ -2155,7 +2155,7 @@ pub const fn rotate_left(x: T, shift: u32) -> #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[rustc_allow_const_fn_unstable(const_trait_impl)] #[miri::intrinsic_fallback_is_spec] pub const fn rotate_right(x: T, shift: u32) -> T { // Make sure to call the intrinsic for `funnel_shr`, not the fallback impl. @@ -2251,11 +2251,11 @@ pub const fn saturating_sub(a: T, b: T) -> T; /// /// Safe versions of this intrinsic are available on the integer primitives /// via the `funnel_shl` method. For example, [`u32::funnel_shl`]. +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] -#[unstable(feature = "funnel_shifts", issue = "145686")] #[track_caller] +#[rustc_allow_const_fn_unstable(const_trait_impl, core_intrinsics_fallbacks)] #[miri::intrinsic_fallback_is_spec] pub const unsafe fn unchecked_funnel_shl( a: T, @@ -2279,11 +2279,11 @@ pub const unsafe fn unchecked_funnel_shl( /// /// Safer versions of this intrinsic are available on the integer primitives /// via the `funnel_shr` method. For example, [`u32::funnel_shr`] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] -#[unstable(feature = "funnel_shifts", issue = "145686")] #[track_caller] +#[rustc_allow_const_fn_unstable(const_trait_impl, core_intrinsics_fallbacks)] #[miri::intrinsic_fallback_is_spec] pub const unsafe fn unchecked_funnel_shr( a: T, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d7d8d32ed88e7..788140e0fca7c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -131,7 +131,6 @@ #![feature(final_associated_functions)] #![feature(freeze_impls)] #![feature(fundamental)] -#![feature(funnel_shifts)] #![feature(impl_restriction)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 514c2aa1c9bd1..d1a68412247ef 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1074,13 +1074,20 @@ pub const trait Destruct: PointeeSized {} #[rustc_dyn_incompatible_trait] pub trait Tuple {} +// HACK(khyperia): if this is missing, the gca macro's `implied_by = "gca_adts"` emits an error +#[unstable(feature = "gca_adts", issue = "163420")] +#[expect(dead_code)] +struct HackGcaAdtsFeature; + /// Creates a new style directly represented const argument. /// ```ignore (cannot test this from within core yet) /// const BAR: usize = gca!(N); /// const FOO: usize = gca!(BAR::); /// ``` #[rustc_builtin_macro(gca)] -#[unstable(feature = "gca_min_const_items", issue = "132980")] +// HACK: abuse implied_by, this should be enabled if gca_min_const_items or gca_adts is enabled, +// neither one is more particularly special than the other +#[unstable(feature = "gca_min_const_items", issue = "132980", implied_by = "gca_adts")] #[macro_export] macro_rules! gca { ($($arg:tt)*) => { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index e12e8c7dffc43..355e9a3c59da7 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1,6 +1,6 @@ //! Definitions of integer that is known not to equal zero. -use super::{IntErrorKind, ParseIntError}; +use super::{IntErrorKind, ParseIntError, TryFromIntError}; use crate::clone::{TrivialClone, UseCloned}; use crate::cmp::Ordering; use crate::hash::{Hash, Hasher}; @@ -9,7 +9,7 @@ use crate::num::imp; use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign}; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::str::FromStr; -use crate::{fmt, intrinsics, ptr, ub_checks}; +use crate::{fmt, intrinsics, ptr, slice, ub_checks}; /// A marker trait for primitive types which can be zero. /// @@ -305,6 +305,114 @@ where } } +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T> From<&'a NonZero> for &'a T +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: &'a NonZero) -> &'a T { + nonzero.as_ref() + } +} + +// FIXME: see library/std/tests/slice-from-array-issue-113238.rs +/* +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T> From<&'a [NonZero]> for &'a [T] +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: &'a [NonZero]) -> &'a [T] { + nonzero.as_zeroable() + } +} +impl [NonZero] +where + T: ZeroablePrimitive, +{ + /// Implementation of `From<&[NonZero]> for &[T]`. + #[must_use] + #[inline] + fn as_zeroable(&self) -> &[T] { + // SAFETY: `repr(transparent)` ensures that `NonZero` has same layout as `T`, and thus + // `[NonZero]` has same layout as `[T]` + unsafe { &*(slice::from_raw_parts(self.as_ptr().cast::(), self.len())) } + } +} +*/ + +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl From<[NonZero; N]> for [T; N] +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: [NonZero; N]) -> [T; N] { + nonzero.into_zeroable() + } +} + +// FIXME: can't detect that ZeroablePrimitive is a sealed trait +macro_rules! impl_ref_try_from { + ($($t:ty),* $(,)?) => { + $( + #[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] + impl<'a> TryFrom<&'a $t> for &'a NonZero<$t> { + type Error = TryFromIntError; + + #[inline] + fn try_from(zeroable: &'a $t) -> Result<&'a NonZero<$t>, TryFromIntError> { + NonZero::from_ref(zeroable).ok_or(TryFromIntError(IntErrorKind::Zero)) + } + } + )* + } +} + +impl_ref_try_from! { + u8, + u16, + u32, + u64, + u128, + usize, + i8, + i16, + i32, + i64, + i128, + isize, + char, +} + +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T> TryFrom<&'a [T]> for &'a [NonZero] +where + T: ZeroablePrimitive, +{ + type Error = TryFromIntError; + + #[inline] + fn try_from(zeroable: &'a [T]) -> Result<&'a [NonZero], TryFromIntError> { + NonZero::from_slice(zeroable).ok_or(TryFromIntError(IntErrorKind::Zero)) + } +} + +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl TryFrom<[T; N]> for [NonZero; N] +where + T: ZeroablePrimitive, +{ + type Error = TryFromIntError; + + #[inline] + fn try_from(zeroable: [T; N]) -> Result<[NonZero; N], TryFromIntError> { + NonZero::from_array(zeroable).ok_or(TryFromIntError(IntErrorKind::Zero)) + } +} + #[stable(feature = "nonzero_bitor", since = "1.45.0")] #[rustc_const_unstable(feature = "const_ops", issue = "143802")] const impl BitOr for NonZero @@ -460,6 +568,45 @@ where } } + /// Implementation of `From<&NonZero> for &T`. + #[must_use] + #[inline] + fn as_ref(&self) -> &T { + // SAFETY: `repr(transparent)` ensures that `NonZero` has same layout as `T` + unsafe { &*(ptr::from_ref(self).cast::()) } + } + + /// Implementation of `TryFrom<&T> for &NonZero`. + #[must_use] + #[inline] + fn from_ref(n: &T) -> Option<&Self> { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + let opt_n = unsafe { &*(ptr::from_ref(n).cast::>()) }; + + opt_n.as_ref() + } + + /// Implementation of `TryFrom<&[T]> for &[NonZero]`. + #[must_use] + #[inline] + fn from_slice(n: &[T]) -> Option<&[Self]> { + if n.iter().all(|x| NonZero::new(*x).is_some()) { + // SAFETY: We explicitly checked that all elements are nonzero, and because of `repr(transparent)` + // the layout remains unchanged + Some(unsafe { slice::from_raw_parts(n.as_ptr().cast::>(), n.len()) }) + } else { + None + } + } + + /// Implementation of `TryFrom<[T; N]> for [NonZero; N]`. + #[must_use] + #[inline] + fn from_array(n: [T; N]) -> Option<[Self; N]> { + n.try_map(NonZero::new) + } + /// Returns the contained value as a primitive type. #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] @@ -487,6 +634,18 @@ where } } +impl [NonZero; N] +where + T: ZeroablePrimitive, +{ + /// Implementation of `From<[NonZero; N]> for [T; N]`. + #[must_use] + #[inline] + fn into_zeroable(self) -> [T; N] { + self.map(NonZero::get) + } +} + macro_rules! nonzero_integer { ( #[$stability:meta] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a53c11e2d876d..fcda1edcf4cb2 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -526,8 +526,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(funnel_shifts)] - /// #[doc = concat!("let a = ", $rot_op, "_", stringify!($SelfT), ";")] #[doc = concat!("let b = ", $fsh_op, "_", stringify!($SelfT), ";")] /// @@ -547,10 +545,8 @@ macro_rules! uint_impl { /// rotating by an unbounded amount like [`rotate_left`](Self::rotate_left) does: /// /// ```should_panic - /// #![feature(funnel_shifts)] /// # #![feature(cfg_overflow_checks)] /// # #[cfg(overflow_checks)] { - /// #[doc = concat!("let a = ", stringify!($SelfT), "::MAX;")] /// // Okay #[doc = concat!("let _ = a.rotate_left(", stringify!($SelfT), "::BITS);")] @@ -559,8 +555,8 @@ macro_rules! uint_impl { /// # } /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic"); /// ``` - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] @@ -597,8 +593,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(funnel_shifts)] - /// #[doc = concat!("let a = ", $rot_op, "_", stringify!($SelfT), ";")] #[doc = concat!("let b = ", $fsh_op, "_", stringify!($SelfT), ";")] /// @@ -618,10 +612,8 @@ macro_rules! uint_impl { /// rotating by an unbounded amount like [`rotate_right`](Self::rotate_right) does: /// /// ```should_panic - /// #![feature(funnel_shifts)] /// # #![feature(cfg_overflow_checks)] /// # #[cfg(overflow_checks)] { - /// #[doc = concat!("let a = ", stringify!($SelfT), "::MAX;")] /// // Okay #[doc = concat!("let _ = a.rotate_right(", stringify!($SelfT), "::BITS);")] @@ -630,8 +622,8 @@ macro_rules! uint_impl { /// # } /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic"); /// ``` - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] @@ -654,8 +646,9 @@ macro_rules! uint_impl { #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")] /// i.e. when [`funnel_shl`](Self::funnel_shl) would panic. /// - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_trait_impl)] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[track_caller] @@ -680,8 +673,9 @@ macro_rules! uint_impl { #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")] /// i.e. when [`funnel_shr`](Self::funnel_shr) would panic. /// - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_trait_impl)] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[track_caller] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index f1d412eeefcf3..9d898df3c6d3c 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1343,8 +1343,6 @@ impl Result { /// # Examples /// /// ``` - /// # #![feature(unwrap_infallible)] - /// /// fn only_good_news() -> Result { /// Ok("this is fine".into()) /// } @@ -1352,7 +1350,7 @@ impl Result { /// let s: String = only_good_news().into_ok(); /// println!("{s}"); /// ``` - #[unstable(feature = "unwrap_infallible", issue = "61695")] + #[stable(feature = "unwrap_infallible", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] @@ -1379,8 +1377,6 @@ impl Result { /// # Examples /// /// ``` - /// # #![feature(unwrap_infallible)] - /// /// fn only_bad_news() -> Result { /// Err("Oops, it failed".into()) /// } @@ -1388,7 +1384,7 @@ impl Result { /// let error: String = only_bad_news().into_err(); /// println!("{error}"); /// ``` - #[unstable(feature = "unwrap_infallible", issue = "61695")] + #[stable(feature = "unwrap_infallible", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 69bc6edd1b833..1334b551217a8 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -65,7 +65,6 @@ #![feature(fmt_internals)] #![feature(formatting_options)] #![feature(freeze)] -#![feature(funnel_shifts)] #![feature(future_join)] #![feature(generic_assert_internals)] #![feature(hasher_prefixfree_extras)] @@ -130,7 +129,6 @@ #![feature(uint_gather_scatter_bits)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(implicit_provenance_casts)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f716f49ffd60a..baa9f8d769c82 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -313,7 +313,6 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // // Library features (core): @@ -347,7 +346,6 @@ #![feature(fmt_internals)] #![feature(fn_static)] #![feature(formatting_options)] -#![feature(funnel_shifts)] #![feature(generic_atomic)] #![feature(hash_map_internals)] #![feature(hash_map_macro)] @@ -758,7 +756,7 @@ pub use core::concat_bytes; )] #[unstable(feature = "derive_macro_global_path", issue = "154645")] pub use core::derive; -#[unstable(feature = "gca_min_const_items", issue = "132980")] +#[unstable(feature = "gca_min_const_items", issue = "132980", implied_by = "gca_adts")] pub use core::gca; #[stable(feature = "matches_macro", since = "1.42.0")] pub use core::matches; diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 513ecc5e5489d..2b7fb159130d9 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -32,7 +32,6 @@ x86_amx_intrinsics, f16, aarch64_unstable_target_feature, - funnel_shifts, avx10_target_feature, const_trait_impl, const_cmp, diff --git a/src/doc/unstable-book/src/language-features/gca-adts.md b/src/doc/unstable-book/src/language-features/gca-adts.md new file mode 100644 index 0000000000000..49905d57a9a4c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/gca-adts.md @@ -0,0 +1,21 @@ +# gca_adts + +Enables ADTs under the generic const args family of features (e.g. `gca!` macro). + +The tracking issue for this feature is: [#163420] + +[#163420]: https://github.com/rust-lang/rust/issues/163420 + +## Examples + +```rust +#![feature(gca_min_const_items, min_adt_const_params, gca_adts)] + +use std::gca; + +struct S; + +fn main() { + let _: S = S::; +} +``` diff --git a/src/doc/unstable-book/src/language-features/gca-min-const-items.md b/src/doc/unstable-book/src/language-features/gca-min-const-items.md index 4027e782714ed..486db1f50885b 100644 --- a/src/doc/unstable-book/src/language-features/gca-min-const-items.md +++ b/src/doc/unstable-book/src/language-features/gca-min-const-items.md @@ -1,6 +1,6 @@ # gca_min_const_items -Enables the generic const args MVP (paths to direct const items and constructors for ADTs and primitives). +Enables the generic const args MVP (paths to direct const items and primitives). The tracking issue for this feature is: [#132980] diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index b56f6f5800eee..c8e143b49911b 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -72,7 +72,7 @@ it is necessary for them. --> - + {ptr.pointer->value} @@ -87,7 +87,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -102,7 +102,7 @@ - + {ptr.pointer->value} @@ -117,7 +117,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -131,7 +131,7 @@ - + {ptr.pointer->data} @@ -146,7 +146,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -160,7 +160,7 @@ - + {ptr.pointer->data} @@ -175,7 +175,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fd804b1e5831e..c34b33d9c92f5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -24,7 +24,7 @@ use rustc_metadata::rendered_const; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_resolve::rustdoc::{ - DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments, + DocFragment, add_doc_fragment, attrs_to_doc_fragments, span_of_fragments, }; use rustc_session::Session; use rustc_span::def_id::{CRATE_DEF_ID, ModId}; @@ -461,13 +461,15 @@ impl Item { } pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool { + use rustc_ast::attr::AttributeExt; + self.item_id .as_def_id() .map(|did| { - inner_docs( - #[allow(deprecated)] - tcx.get_all_attrs(did), - ) + #[allow(deprecated)] + tcx.get_all_attrs(did).iter().any(|attr| { + attr.doc_resolution_scope().is_some_and(|style| style == ast::AttrStyle::Inner) + }) }) .unwrap_or(false) } diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs index a0fc623c20c48..29a8fd5e2678e 100644 --- a/src/librustdoc/clean/types/tests.rs +++ b/src/librustdoc/clean/types/tests.rs @@ -12,6 +12,7 @@ fn create_doc_fragment(s: &str) -> Vec { kind: DocFragmentKind::Sugared(CommentKind::Line), indent: 0, from_expansion: false, + style: rustc_ast::AttrStyle::Outer, }] } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index fb89a6547a931..170352dabf656 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -777,7 +777,9 @@ impl Options { } } - let edition = config::parse_crate_edition(early_dcx, matches); + // We don't want rustdoc invocations to complain about the lack of `--edition`. + let has_input = false; + let edition = config::parse_crate_edition(early_dcx, matches, has_input); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d7815e64178a7..ac7cf2a42bd3b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -21,8 +21,8 @@ use rustc_middle::ty; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_resolve::rustdoc::pulldown_cmark::LinkType; use rustc_resolve::rustdoc::{ - MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, prepare_to_doc_link_resolution, - source_span_for_markdown_range, strip_generics_from_path, + DocStrings, MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, + prepare_to_doc_link_resolution, source_span_for_markdown_range, strip_generics_from_path, }; use rustc_span::def_id::ModId; use rustc_span::edit_distance::find_best_match_for_name; @@ -1091,14 +1091,7 @@ impl LinkCollector<'_, '_> { return; } - let mut try_insert_links = |item_id, doc: &str| { - if should_skip_link_resolution(item_id) { - return; - } - let module_id = match tcx.def_kind(item_id) { - DefKind::Mod if item.inner_docs(tcx) => ModId::new_unchecked(item_id), - _ => find_nearest_parent_module(tcx, item_id).unwrap(), - }; + let mut try_insert_links_inner = |item_id, module_id, doc: &str| { for md_link in preprocessed_markdown_links(&doc) { let link = self.resolve_link(&doc, item, item_id, module_id, &md_link); if let Some(link) = link { @@ -1112,16 +1105,45 @@ impl LinkCollector<'_, '_> { } }; + let mut try_insert_links = |item_id, docs: &DocStrings| { + if should_skip_link_resolution(item_id) { + return; + } + match tcx.def_kind(item_id) { + DefKind::Mod => { + if !docs.outer.is_empty() { + try_insert_links_inner( + item_id, + find_nearest_parent_module(tcx, item_id).unwrap(), + &docs.outer, + ); + } + if !docs.inner.is_empty() { + try_insert_links_inner(item_id, ModId::new_unchecked(item_id), &docs.inner); + } + } + _ => { + // It's the same handling for non-module items. + let module_id = find_nearest_parent_module(tcx, item_id).unwrap(); + try_insert_links_inner( + item_id, + module_id, + &format!("{}{}", docs.outer, docs.inner), + ); + } + } + }; + // We want to resolve in the lexical scope of the documentation. // In the presence of re-exports, this is not the same as the module of the item. // Rather than merging all documentation into one, resolve it one attribute at a time // so we know which module it came from. for (item_id, doc) in prepare_to_doc_link_resolution(&item.attrs.doc_strings) { - if !may_have_doc_links(&doc) { + if !may_have_doc_links(&doc.inner) && !may_have_doc_links(&doc.outer) { continue; } - debug!("combined_docs={doc}"); + debug!("combined_docs=outer: {} inner: {}", doc.outer, doc.inner); // NOTE: if there are links that start in one crate and end in another, this will not resolve them. // This is a degenerate case and it's not supported by rustdoc. let item_id = item_id.unwrap_or_else(|| item.item_id.expect_def_id()); @@ -1163,7 +1185,7 @@ impl LinkCollector<'_, '_> { } else { item.item_id.expect_def_id() }; - try_insert_links(item_id, note) + try_insert_links(item_id, &DocStrings { outer: note.to_owned(), inner: String::new() }); } } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 902054c917699..e02fbae3e0568 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -30,10 +30,11 @@ struct LinkData { pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { let hunks = prepare_to_doc_link_resolution(&item.attrs.doc_strings); for (item_id, doc) in hunks { - if let Some(item_id) = item_id.or(item.def_id()) - && !doc.is_empty() - { - check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + if let Some(item_id) = item_id.or(item.def_id()) { + if !doc.outer.is_empty() || !doc.inner.is_empty() { + let doc = format!("{}{}", doc.outer, doc.inner); + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + } } } } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 435f787f7012f..87bb44875aee9 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -8,9 +8,9 @@ #![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::literal_string_with_formatting_args, clippy::must_use_candidate)] #![warn( diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 7a155b5885a8c..1eec6bf4419db 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,7 +1,7 @@ +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(deref_patterns)] #![feature(macro_metavar_expr)] #![feature(rustc_private)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 94e949b78d0a1..1037b2c6375b7 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -405,11 +405,10 @@ impl TestProps { } } - if let Some(edition) = self.edition.or(config.edition) { - // The edition is added at the start, since flags from //@compile-flags must be passed - // to rustc last. - self.compile_flags.insert(0, format!("--edition={edition}")); - } + let edition = self.edition.or(config.edition).unwrap_or(Edition::Year(2015)); + // The edition is added at the start, since flags from //@compile-flags must be passed + // to rustc last. + self.compile_flags.insert(0, format!("--edition={edition}")); } fn update_pass_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { diff --git a/src/tools/compiletest/src/rustdoc_gui_test.rs b/src/tools/compiletest/src/rustdoc_gui_test.rs index 5a768519f616d..4e1d1138b3168 100644 --- a/src/tools/compiletest/src/rustdoc_gui_test.rs +++ b/src/tools/compiletest/src/rustdoc_gui_test.rs @@ -33,7 +33,10 @@ impl RustdocGuiTestProps { let props = TestProps::from_file(test_file_path, None, &config); - let TestProps { compile_flags, run_flags, .. } = props; + let TestProps { mut compile_flags, run_flags, .. } = props; + // We don't want to pass `--edition=2015` in, which is being set by default by + // `TestProps::from_file`. + compile_flags.remove(0); Self { compile_flags, run_flags } } } diff --git a/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs b/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs index 40b61f65ebe88..b64f4551fd605 100644 --- a/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs +++ b/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs b/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs index 9582265639716..922144d6d6042 100644 --- a/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs +++ b/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/memleak_rc.stderr b/src/tools/miri/tests/fail/memleak_rc.stderr index a77cf55b0c317..26156050ae5d3 100644 --- a/src/tools/miri/tests/fail/memleak_rc.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.stderr @@ -1,5 +1,5 @@ error: memory leaked: ALLOC (Rust heap, SIZE, ALIGN), allocated here: - --> RUSTLIB/alloc/src/rc.rs:LL:CC + --> RUSTLIB/alloc/src/rcs/rc.rs:LL:CC | LL | Self::from_inner(Box::into_non_null(Box::new(RcInner { | _________________________________________________^ @@ -11,7 +11,7 @@ LL | | }))) | = note: stack backtrace: 0: std::rc::Rc::>>::new - at RUSTLIB/alloc/src/rc.rs:LL:CC + at RUSTLIB/alloc/src/rcs/rc.rs:LL:CC 1: main at tests/fail/memleak_rc.rs:LL:CC diff --git a/src/tools/miri/tests/pass/intrinsics/integer.rs b/src/tools/miri/tests/pass/intrinsics/integer.rs index 555a85147ee5f..2260068704adf 100644 --- a/src/tools/miri/tests/pass/intrinsics/integer.rs +++ b/src/tools/miri/tests/pass/intrinsics/integer.rs @@ -1,5 +1,5 @@ //@run-native -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] use std::intrinsics::*; fn main() { diff --git a/tests/codegen-llvm/debuginfo-cyclic-structure.rs b/tests/codegen-llvm/debuginfo-cyclic-structure.rs index b8cc544774158..dc7193dd08ed2 100644 --- a/tests/codegen-llvm/debuginfo-cyclic-structure.rs +++ b/tests/codegen-llvm/debuginfo-cyclic-structure.rs @@ -3,7 +3,7 @@ // Check that debug information exists for structures containing loops (cyclic references). // Previously it may incorrectly prune member information during recursive type inference check. -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Arc Arc<[u64]> { // CHECK-LABEL: @new_uninit #[no_mangle] pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { - // CHECK: call alloc::sync::arcinner_layout_for_value_layout - // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout + // CHECK: call alloc::rcs::arc::arcinner_layout_for_value_layout + // CHECK-NOT: call alloc::rcs::arc::arcinner_layout_for_value_layout let mut arc = Arc::new_uninit(); unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]); unsafe { arc.assume_init() } @@ -30,8 +30,8 @@ pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { // CHECK-LABEL: @new_uninit_slice #[no_mangle] pub fn new_uninit_slice(x: u64) -> Arc<[u64]> { - // CHECK: call alloc::sync::arcinner_layout_for_value_layout - // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout + // CHECK: call alloc::rcs::arc::arcinner_layout_for_value_layout + // CHECK-NOT: call alloc::rcs::arc::arcinner_layout_for_value_layout let mut arc = Arc::new_uninit_slice(1000); for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } { elem.write(x); diff --git a/tests/debuginfo/rc_arc.rs b/tests/debuginfo/rc_arc.rs index 4399dfe54e7a5..adeb96dba1b80 100644 --- a/tests/debuginfo/rc_arc.rs +++ b/tests/debuginfo/rc_arc.rs @@ -27,37 +27,37 @@ //@ cdb-command:g //@ cdb-command:dx rc,d -//@ cdb-check:rc,d : 111 [Type: alloc::rc::Rc] +//@ cdb-check:rc,d : 111 [Type: alloc::rcs::rc::Rc] //@ cdb-check: [Reference count] : 11 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx weak_rc,d -//@ cdb-check:weak_rc,d : 111 [Type: alloc::rc::Weak] +//@ cdb-check:weak_rc,d : 111 [Type: alloc::rcs::rc::Weak] //@ cdb-check: [Reference count] : 11 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx arc,d -//@ cdb-check:arc,d : 222 [Type: alloc::sync::Arc] +//@ cdb-check:arc,d : 222 [Type: alloc::rcs::arc::Arc] //@ cdb-check: [Reference count] : 21 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx weak_arc,d -//@ cdb-check:weak_arc,d : 222 [Type: alloc::sync::Weak] +//@ cdb-check:weak_arc,d : 222 [Type: alloc::rcs::arc::Weak] //@ cdb-check: [Reference count] : 21 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx dyn_rc,d -//@ cdb-check:dyn_rc,d [Type: alloc::rc::Rc,alloc::alloc::Global>] +//@ cdb-check:dyn_rc,d [Type: alloc::rcs::rc::Rc,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 31 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx dyn_rc_weak,d -//@ cdb-check:dyn_rc_weak,d [Type: alloc::rc::Weak,alloc::alloc::Global>] +//@ cdb-check:dyn_rc_weak,d [Type: alloc::rcs::rc::Weak,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 31 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx slice_rc,d -//@ cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc,alloc::alloc::Global>] +//@ cdb-check:slice_rc,d : { len=3 } [Type: alloc::rcs::rc::Rc,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 41 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] @@ -66,7 +66,7 @@ //@ cdb-check: [2] : 3 [Type: u32] //@ cdb-command:dx slice_rc_weak,d -//@ cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak,alloc::alloc::Global>] +//@ cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rcs::rc::Weak,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 41 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] @@ -75,17 +75,17 @@ //@ cdb-check: [2] : 3 [Type: u32] //@ cdb-command:dx dyn_arc,d -//@ cdb-check:dyn_arc,d [Type: alloc::sync::Arc,alloc::alloc::Global>] +//@ cdb-check:dyn_arc,d [Type: alloc::rcs::arc::Arc,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 51 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx dyn_arc_weak,d -//@ cdb-check:dyn_arc_weak,d [Type: alloc::sync::Weak,alloc::alloc::Global>] +//@ cdb-check:dyn_arc_weak,d [Type: alloc::rcs::arc::Weak,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 51 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx slice_arc,d -//@ cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc,alloc::alloc::Global>] +//@ cdb-check:slice_arc,d : { len=3 } [Type: alloc::rcs::arc::Arc,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 61 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] @@ -94,7 +94,7 @@ //@ cdb-check: [2] : 6 [Type: u32] //@ cdb-command:dx slice_arc_weak,d -//@ cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak,alloc::alloc::Global>] +//@ cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::rcs::arc::Weak,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 61 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 81e3037f1e566..56e9f6a5b9773 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -20,13 +20,13 @@ //@ gdb-check:$4 = ("Hello", "World") //@ gdb-command:print str_in_rc -//@ gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +//@ gdb-check:$5 = alloc::rcs::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} //@ gdb-command:print box_str //@ gdb-check:$6 = alloc::boxed::Box [87, 111, 114, 108, 100] //@ gdb-command:print rc_str -//@ gdb-check:$7 = alloc::rc::Rc {ptr: core::ptr::non_null::NonNull> {pointer: alloc::rc::RcInner {strong: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, weak: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, value: 0x[...]}}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +//@ gdb-check:$7 = alloc::rcs::rc::Rc {ptr: core::ptr::non_null::NonNull> {pointer: alloc::rcs::rc::RcInner {strong: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, weak: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, value: 0x[...]}}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} // === LLDB TESTS ================================================================================== //@ lldb-command:run @@ -56,7 +56,7 @@ // lldb-command:v rc_str // ignore-tidy-linelength -// lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=1 { value = "World" } +// lldb-check:(alloc::rcs::rc::Rc) rc_str = strong=1, weak=1 { value = "World" } #![allow(unused_variables)] diff --git a/tests/debuginfo/thread.rs b/tests/debuginfo/thread.rs index d78dad406ac6e..ee33f921cc033 100644 --- a/tests/debuginfo/thread.rs +++ b/tests/debuginfo/thread.rs @@ -14,7 +14,7 @@ // //@ cdb-command:dx t,d //@ cdb-check:t,d : [...] [Type: std::thread::thread::Thread *] -//@ cdb-check:[...] inner [...][Type: core::pin::Pin >] +//@ cdb-check:[...] inner [...][Type: core::pin::Pin >] use std::thread; diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index b0a28b6c899da..0e43ebda9c3e1 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -68,7 +68,7 @@ fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { fn main() { let mut rustc = bare_rustc(); - rustc.arg("--print=sysroot"); + rustc.arg("--print=sysroot").edition("2015"); let rustc = rustc.into_raw_command(); check_broken_pipe_handled_gracefully(Binary::Rustc, rustc); diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index 45bfaa6041d97..4a5305a87cbfb 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -12,6 +12,7 @@ use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { let out = rustc() + .edition("2015") .crate_name("foo") .crate_type("lib") .emit("obj") diff --git a/tests/run-make/const-destruct-stable-toolchain/rmake.rs b/tests/run-make/const-destruct-stable-toolchain/rmake.rs index 0f36d71f2c874..18d78710f5849 100644 --- a/tests/run-make/const-destruct-stable-toolchain/rmake.rs +++ b/tests/run-make/const-destruct-stable-toolchain/rmake.rs @@ -11,6 +11,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() .input("const-drop.rs") + .edition("2015") .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("consider restricting type parameter `T`") @@ -18,6 +19,7 @@ fn main() { diff().expected_file("const-drop-stable.stderr").actual_text("(rustc)", &out).run(); let out = rustc() .input("const-drop.rs") + .edition("2015") .ui_testing() .run_fail() .assert_stderr_contains( diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index e2ec58f03db19..20679cdb2ed29 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .input("const-super-trait.rs") .env("RUSTC_BOOTSTRAP", "-1") .cfg("feature_enabled") @@ -24,6 +25,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .cfg("feature_enabled") .ui_testing() @@ -36,6 +38,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .env("RUSTC_BOOTSTRAP", "-1") .run_fail() @@ -47,6 +50,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .ui_testing() .run_fail() diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs index 57e0cab92f1ef..f49a848052411 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -10,9 +10,10 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("foo-prev.rs").run(); + rustc().edition("2015").input("foo-prev.rs").run(); let out = rustc() + .edition("2015") .extra_filename("current") .metadata("current") .input("foo-current.rs") diff --git a/tests/run-make/crate-loading-multiple-candidates/rmake.rs b/tests/run-make/crate-loading-multiple-candidates/rmake.rs index ce090850500b8..9775a1672f0cb 100644 --- a/tests/run-make/crate-loading-multiple-candidates/rmake.rs +++ b/tests/run-make/crate-loading-multiple-candidates/rmake.rs @@ -9,8 +9,18 @@ use run_make_support::{bare_rustc, diff, rfs, rustc}; fn main() { // Check that relative paths are preserved in the diagnostic rfs::create_dir("mylibs"); - rustc().input("crateresolve1-1.rs").out_dir("mylibs").extra_filename("-1").run(); - rustc().input("crateresolve1-2.rs").out_dir("mylibs").extra_filename("-2").run(); + rustc() + .edition("2015") + .input("crateresolve1-1.rs") + .out_dir("mylibs") + .extra_filename("-1") + .run(); + rustc() + .edition("2015") + .input("crateresolve1-2.rs") + .out_dir("mylibs") + .extra_filename("-2") + .run(); check("./mylibs"); // Check that symlinks aren't followed when printing the diagnostic @@ -21,6 +31,7 @@ fn main() { fn check(library_path: &str) { let out = rustc() + .edition("2015") .input("multiple-candidates.rs") .library_search_path(library_path) .ui_testing() diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 8f2577861239d..79f14e1851eff 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -6,11 +6,16 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("dependency-1.rs").run(); - rustc().input("dependency-2.rs").extra_filename("2").metadata("2").run(); - rustc().input("dep-2-reexport.rs").extern_("dependency", rust_lib_name("dependency2")).run(); + rustc().edition("2015").input("dependency-1.rs").run(); + rustc().edition("2015").input("dependency-2.rs").extra_filename("2").metadata("2").run(); + rustc() + .edition("2015") + .input("dep-2-reexport.rs") + .extern_("dependency", rust_lib_name("dependency2")) + .run(); let out = rustc() + .edition("2015") .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) diff --git a/tests/run-make/emit-to-stdout/rmake.rs b/tests/run-make/emit-to-stdout/rmake.rs index 19c15b72fe475..851ab3cb45881 100644 --- a/tests/run-make/emit-to-stdout/rmake.rs +++ b/tests/run-make/emit-to-stdout/rmake.rs @@ -13,8 +13,9 @@ use run_make_support::{diff, run_in_tmpdir, rustc}; // Test emitting text outputs to stdout works correctly fn run_diff(name: &str, file_args: &[&str]) { - rustc().emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); - let out = rustc().emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); + rustc().edition("2015").emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); + let out = + rustc().edition("2015").emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); diff().expected_file(name).actual_text("stdout", &out).run(); } @@ -29,7 +30,13 @@ fn run_terminal_err_diff(name: &str) { let terminal = File::options().read(true).write(true).open(r"\\.\CONOUT$").unwrap(); let err = File::create(name).unwrap(); - rustc().emit(format!("{name}=-")).input("test.rs").stdout(terminal).stderr(err).run_fail(); + rustc() + .edition("2015") + .emit(format!("{name}=-")) + .input("test.rs") + .stdout(terminal) + .stderr(err) + .run_fail(); diff().expected_file(format!("emit-{name}.stderr")).actual_file(name).run(); } @@ -47,6 +54,7 @@ fn main() { // Test error for emitting multiple types to stdout rustc() + .edition("2015") .input("test.rs") .emit("asm=-") .emit("llvm-ir=-") @@ -58,6 +66,7 @@ fn main() { // Same as above, but using `-o` rustc() + .edition("2015") .input("test.rs") .output("-") .emit("asm,llvm-ir,dep-info,mir") @@ -69,6 +78,11 @@ fn main() { .run(); // Test that `-o -` redirected to a file works correctly (#26719) - rustc().input("test.rs").output("-").stdout(File::create("out-stdout").unwrap()).run(); + rustc() + .edition("2015") + .input("test.rs") + .output("-") + .stdout(File::create("out-stdout").unwrap()) + .run(); }); } diff --git a/tests/run-make/jobserver-error/rmake.rs b/tests/run-make/jobserver-error/rmake.rs index 265eec7190d4e..80c1562299e72 100644 --- a/tests/run-make/jobserver-error/rmake.rs +++ b/tests/run-make/jobserver-error/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .env("MAKEFLAGS", "--jobserver-auth=1000,1000") .run_fail() @@ -23,6 +24,7 @@ fn main() { diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run(); let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .input("-") .env("MAKEFLAGS", "--jobserver-auth=3,3") diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index b25d892507907..bf6ef980265f1 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -5,6 +5,7 @@ use run_make_support::{Rustc, diff, regex, rustc}; fn run_rustc() -> Rustc { let mut rustc = rustc(); rustc + .edition("2015") .arg("main.rs") // NOTE: `link-self-contained` can vary depending on bootstrap.toml. // Make sure we use a consistent value. @@ -23,9 +24,9 @@ fn run_rustc() -> Rustc { fn main() { // first, compile our linker and our dependencies - rustc().arg("fake-linker.rs").output("fake-linker").run(); - rustc().arg("foo.rs").crate_type("rlib").run(); - rustc().arg("bar.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("fake-linker.rs").output("fake-linker").run(); + rustc().edition("2015").arg("foo.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("bar.rs").crate_type("rlib").run(); // Run rustc with our fake linker, and make sure it shows warnings let warnings = run_rustc().link_arg("run_make_warn").run(); @@ -92,12 +93,14 @@ fn main() { // Make sure we show linker warnings even across `-Z no-link` rustc() + .edition("2015") .arg("-Zno-link") .input("-") .stdin_buf("#![deny(linker_messages)] \n fn main() {}") .run() .assert_stderr_equals(""); rustc() + .edition("2015") .arg("-Zlink-only") .arg("rust_out.rlink") .linker("./fake-linker") @@ -111,6 +114,7 @@ fn main() { // Same thing, but with json output. rustc() + .edition("2015") .error_format("json") .arg("-Zlink-only") .arg("rust_out.rlink") diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs index 753f4abcf32fd..c77475e15abb9 100644 --- a/tests/run-make/missing-unstable-trait-bound/rmake.rs +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -12,6 +12,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .env("RUSTC_BOOTSTRAP", "-1") .input("missing-bound.rs") .run_fail() diff --git a/tests/run-make/multiline-args-value/rmake.rs b/tests/run-make/multiline-args-value/rmake.rs index 3964cbbc1e605..f9e6290f7d919 100644 --- a/tests/run-make/multiline-args-value/rmake.rs +++ b/tests/run-make/multiline-args-value/rmake.rs @@ -3,7 +3,8 @@ use run_make_support::{cwd, diff, rustc}; fn test_and_compare(test_name: &str, flag: &str, val: &str) { let mut cmd = rustc(); - let output = cmd.input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); + let output = + cmd.edition("2015").input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); assert_eq!(output.stdout_utf8(), ""); diff() diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs index b7a3c51db5bfd..7a1c7e4322ddc 100644 --- a/tests/run-make/non-unicode-env/rmake.rs +++ b/tests/run-make/non-unicode-env/rmake.rs @@ -6,7 +6,11 @@ fn main() { let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]); #[cfg(windows)] let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]); - let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail(); + let output = rustc() + .edition("2015") + .input("non_unicode_env.rs") + .env("NON_UNICODE_VAR", non_unicode) + .run_fail(); let expected = rfs::read_to_string("non_unicode_env.stderr"); output.assert_stderr_equals(expected); } diff --git a/tests/run-make/option-output-no-space/rmake.rs b/tests/run-make/option-output-no-space/rmake.rs index 63d2389890155..d77ae4bef12a8 100644 --- a/tests/run-make/option-output-no-space/rmake.rs +++ b/tests/run-make/option-output-no-space/rmake.rs @@ -7,6 +7,7 @@ use run_make_support::rustc; fn main() { // test fake args rustc() + .edition("2015") .input("main.rs") .arg("-optimize") .run() @@ -17,6 +18,7 @@ fn main() { "= note: output filename `-o ptimize` is applied instead of a flag named `optimize`", ); rustc() + .edition("2015") .input("main.rs") .arg("-o0") .run() @@ -26,9 +28,10 @@ fn main() { .assert_stderr_contains( "= note: output filename `-o 0` is applied instead of a flag named `o0`", ); - rustc().input("main.rs").arg("-o1").run(); + rustc().edition("2015").input("main.rs").arg("-o1").run(); // test real args by iter optgroups rustc() + .edition("2015") .input("main.rs") .arg("-out-dir") .run() @@ -43,6 +46,7 @@ fn main() { ); // test real args by iter CG_OPTIONS rustc() + .edition("2015") .input("main.rs") .arg("-opt_level") .run() @@ -58,6 +62,7 @@ fn main() { ); // separater in-sensitive rustc() + .edition("2015") .input("main.rs") .arg("-opt-level") .run() @@ -72,6 +77,7 @@ fn main() { `-o pt-level`", ); rustc() + .edition("2015") .input("main.rs") .arg("-overflow-checks") .run() @@ -88,10 +94,28 @@ fn main() { ); // No warning for Z_OPTIONS - rustc().input("main.rs").arg("-oom").run().assert_stderr_equals(""); + rustc().edition("2015").input("main.rs").arg("-oom").run().assert_stderr_equals(""); // test no warning when there is space between `-o` and arg - rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("ptimize") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("--out-dir") + .arg("xxx") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("out-dir") + .run() + .assert_stderr_equals(""); } diff --git a/tests/run-make/overwrite-input/rmake.rs b/tests/run-make/overwrite-input/rmake.rs index bdf7860caa8a0..581fee8fe0136 100644 --- a/tests/run-make/overwrite-input/rmake.rs +++ b/tests/run-make/overwrite-input/rmake.rs @@ -8,8 +8,9 @@ use run_make_support::{diff, rustc}; fn main() { - let file_out = rustc().input("main.rs").output("main.rs").run_fail().stderr_utf8(); - let folder_out = rustc().input("main.rs").output(".").run_fail().stderr_utf8(); + let file_out = + rustc().edition("2015").input("main.rs").output("main.rs").run_fail().stderr_utf8(); + let folder_out = rustc().edition("2015").input("main.rs").output(".").run_fail().stderr_utf8(); diff().expected_file("file.stderr").actual_text("actual-file-stderr", file_out).run(); diff().expected_file("folder.stderr").actual_text("actual-folder-stderr", folder_out).run(); } diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs index 1ac68c95559c6..e5793130c6550 100644 --- a/tests/run-make/pointer-auth-link-with-c/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{build_native_static_lib, cc, is_windows_msvc, llvm_ar, ru fn main() { build_native_static_lib("test"); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -30,6 +31,7 @@ fn main() { let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -46,6 +48,7 @@ fn main() { // let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; // llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); // rustc() + // .edition("2015") // .arg("-Cunsafe-allow-abi-mismatch=branch-protection") // .arg("-Zbranch-protection=bti,pac-ret,pc,leaf") // .input("test.rs") diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs index 62cf0483f320d..695ebec5cb68e 100644 --- a/tests/run-make/print-request-help-stable-unstable/rmake.rs +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{diff, rustc, similar}; fn main() { let stable_invalid_print_request_help = rustc() + .edition("2015") .env("RUSTC_BOOTSTRAP", "-1") .cfg("force_stable") .print("xxx") @@ -20,7 +21,8 @@ fn main() { .actual_text("stable_invalid_print_request_help", &stable_invalid_print_request_help) .run(); - let unstable_invalid_print_request_help = rustc().print("xxx").run_fail().stderr_utf8(); + let unstable_invalid_print_request_help = + rustc().edition("2015").print("xxx").run_fail().stderr_utf8(); assert!(unstable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("unstable-invalid-print-request-help.err") diff --git a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs index 608adebbd54f2..87d57ca1f76ac 100644 --- a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs +++ b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs @@ -19,6 +19,7 @@ fn main() { rustc().input(runtool_path).run(); let output = rustdoc() + .edition("2015") .input(doctests_path) .arg("--test") // for the outer test suite diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs index 5791bf01bba2b..dbea1bda2cab5 100644 --- a/tests/run-make/target-cpu-native/rmake.rs +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{run, rustc}; fn main() { let out = rustc() + .edition("2015") .input("foo.rs") .arg("-Ctarget-cpu=native") .arg("-Zverify-llvm-ir") diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs index 101711b0d2c70..56833569e54bf 100644 --- a/tests/run-make/unknown-mod-stdin/rmake.rs +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -14,7 +14,8 @@ use run_make_support::{diff, rustc}; fn main() { - let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); + let out = + rustc().edition("2015").crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); diff() .actual_text("actual-stdout", out.stdout_utf8()) .expected_file("unknown-mod.stdout") diff --git a/tests/run-make/unspecified-edition/help-unspecified-edition.stdout b/tests/run-make/unspecified-edition/help-unspecified-edition.stdout new file mode 100644 index 0000000000000..eea9ae297848a --- /dev/null +++ b/tests/run-make/unspecified-edition/help-unspecified-edition.stdout @@ -0,0 +1,74 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg Configure the compilation environment. + SPEC supports the syntax `[=""]`. + --check-cfg + Provide list of expected cfgs for checking + -L [=] Add a directory to the library search path. The + optional KIND can be one of + (default: + all). + -l [[:]=][:] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + (default: dylib). + Optional comma separated MODIFIERS + + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type + Comma separated list of types of crates + for the compiler to emit + --crate-name + Specify the name of the crate being built + --edition <2015|2018|2021|2024|future> + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2024. + --emit [=] + Comma separated list of types of output for the + compiler to emit. + Each TYPE has the default FILE name: + * asm - CRATE_NAME.s + * llvm-bc - CRATE_NAME.bc + * dep-info - CRATE_NAME.d + * link - (platform and crate-type dependent) + * llvm-ir - CRATE_NAME.ll + * metadata - libCRATE_NAME.rmeta + * mir - CRATE_NAME.mir + * obj - CRATE_NAME.o + * thin-link-bitcode - CRATE_NAME.indexing.o + --print [=] + Compiler information to print on stdout (or to a file) + INFO may be one of + . + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=3 + -o Write output to FILENAME + --out-dir Write output to compiler-chosen filename in DIR + --explain Provide a detailed explanation of an error message + --test Build a test harness + --target + Target tuple for which the code is compiled + -A, --allow Set lint allowed + -W, --warn Set lint warnings + --force-warn + Set lint force-warn + -D, --deny Set lint denied + -F, --forbid Set lint forbidden + --cap-lints + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen [=] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/unspecified-edition/main.rs b/tests/run-make/unspecified-edition/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/unspecified-edition/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/unspecified-edition/rmake.rs b/tests/run-make/unspecified-edition/rmake.rs new file mode 100644 index 0000000000000..26b6b7d511200 --- /dev/null +++ b/tests/run-make/unspecified-edition/rmake.rs @@ -0,0 +1,37 @@ +// When calling `rustc` without an explicit edition, emit a note asking the user to specify one, +// clarifying that the default is 2015. + +use run_make_support::{bare_rustc, diff, rustc, rustdoc}; + +fn main() { + rustc().edition("2015").input("main.rs").run().assert_stderr_not_contains("--edition"); + let out = rustc().input("main.rs").run().assert_stderr_contains("--edition").stderr_utf8(); + diff().expected_file("unspecified-edition.stderr").actual_text("(rustc)", &out).run(); + + // Ensure that we only mention --edition when compiling code. + let out = rustc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_file("unspecified-edition-without-compiling.stderr") + .actual_text("(rustc)", &out) + .run(); + + // Ensure that we dont mention --edition when running rustdoc. + let out = rustdoc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_text("(test)", "error: missing file operand\n\n") + .actual_text("(rustc)", &out) + .run(); + + let out = + rustdoc().input("main.rs").run().assert_stderr_not_contains("--edition").stderr_utf8(); + diff().expected_text("(test)", "").actual_text("(rustc)", &out).run(); + + // Ensure that we don't mention --edition when getting help. + let result = rustc().arg("--help").run(); + result.assert_stderr_not_contains("--edition"); + let out = result.stdout_utf8(); + let err = result.stderr_utf8(); + diff().expected_file("help-unspecified-edition.stdout").actual_text("(rustc)", &out).run(); + diff().expected_text("(test)", "").actual_text("(rustc)", &err).run(); + bare_rustc().arg("--version").run().assert_stderr_not_contains("--edition"); +} diff --git a/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr new file mode 100644 index 0000000000000..c36ecca4af4a2 --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr @@ -0,0 +1,4 @@ +error: no input filename given + +error: aborting due to 1 previous error + diff --git a/tests/run-make/unspecified-edition/unspecified-edition.stderr b/tests/run-make/unspecified-edition/unspecified-edition.stderr new file mode 100644 index 0000000000000..0a15e47d49fae --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition.stderr @@ -0,0 +1,2 @@ +`--edition` is unspecified, defaulting to `2015` while the latest is `2024`; it must be one of: <2015|2018|2021|2024|future> + diff --git a/tests/rustdoc-html/intra-doc/mixed-inner-outer.rs b/tests/rustdoc-html/intra-doc/mixed-inner-outer.rs new file mode 100644 index 0000000000000..5a0f92522662d --- /dev/null +++ b/tests/rustdoc-html/intra-doc/mixed-inner-outer.rs @@ -0,0 +1,22 @@ +// This test ensures that when a documentation is composed of both inner and outer +// doc comments, the intra-doc link resolution still works as expected. +// Regression test for . +// Regression test for . +// Regression test for . + +#![crate_name = "foo"] +#![deny(rustdoc::broken_intra_doc_links)] + +//@ has foo/demo/index.html +//@ has - '//a[@href="../struct.Foo.html"]' 'Foo' +//@ has - '//a[@href="struct.DemoStruct.html"]' 'DemoStruct' + +/// Outer doc-comment [`Foo`]. +pub mod demo { + //! + //! Inner doc-comment with link: [`DemoStruct`] + + pub struct DemoStruct; +} + +pub struct Foo; diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs index 7600c4882a91c..b4bfdb494a863 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs @@ -1,10 +1,13 @@ //@ compile-flags: -Znext-solver=globally -#![allow(incomplete_features)] -#![feature(gca_macroless_args)] -#![feature(gca_macroless_items)] -#![feature(gca_const_items, gca_min_const_items)] -#![feature(min_adt_const_params)] +#![feature( + gca_adts, + gca_const_items, + gca_macroless_args, + gca_macroless_items, + gca_min_const_items, + min_adt_const_params +)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr index 9dd229cc46a34..42d1d8b5fd1d7 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr @@ -1,5 +1,5 @@ error: the constant `"foo"` is not of type `()` - --> $DIR/const-pattern-field-type-mismatch-162394.rs:17:5 + --> $DIR/const-pattern-field-type-mismatch-162394.rs:20:5 | LL | const A2: Foo = Self::FooA("foo"); | ^^^^^^^^^^^^^ expected `()`, found `&'static str` diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.rs b/tests/ui/const-generics/gca/gca-macro-fn-call.rs index 6035c14e5eb75..73945b14af4b9 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.rs +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.rs @@ -13,10 +13,14 @@ //! tuple-variant constructor (unions, primitives, foreign types), not just structs. //@ compile-flags: -Znext-solver -#![feature(gca_min_const_items, gca_macroless_args)] -#![feature(gca_const_items)] -#![feature(extern_types)] -#![expect(incomplete_features)] +#![feature( + extern_types, + gca_adts, + gca_const_items, + gca_macroless_args, + gca_min_const_items, + min_adt_const_params +)] struct FieldName([u8; N]); diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.stderr b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr index 1399bcb1dee92..4b7bf15ace96d 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.stderr +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr @@ -1,29 +1,29 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:35:23 + --> $DIR/gca-macro-fn-call.rs:39:23 | LL | fn bad(_: FieldName<{ FieldName::len() }>) {} | ^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:44:31 + --> $DIR/gca-macro-fn-call.rs:48:31 | LL | fn bad_tracing(_: FieldName<{ FieldName::len_of("id") }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:61:23 + --> $DIR/gca-macro-fn-call.rs:65:23 | LL | fn bad_union(_: Tag<{ Tag::width() }>) {} | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:70:28 + --> $DIR/gca-macro-fn-call.rs:74:28 | LL | fn bad_prim(_: FieldName<{ u32::from_str_radix("10", 10) }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:81:31 + --> $DIR/gca-macro-fn-call.rs:85:31 | LL | fn bad_foreign(_: FieldName<{ Opaque::foo() }>) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca_adts/missing-dependent-features.rs b/tests/ui/const-generics/gca_adts/missing-dependent-features.rs new file mode 100644 index 0000000000000..55a6338dadb64 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/missing-dependent-features.rs @@ -0,0 +1,3 @@ +#![feature(gca_adts)] +//~^ ERROR `gca_adts` requires `min_adt_const_params` or `adt_const_params` to be enabled +fn main() {} diff --git a/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr b/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr new file mode 100644 index 0000000000000..19c96d5d7bd9e --- /dev/null +++ b/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr @@ -0,0 +1,10 @@ +error: `gca_adts` requires `min_adt_const_params` or `adt_const_params` to be enabled + --> $DIR/missing-dependent-features.rs:1:12 + | +LL | #![feature(gca_adts)] + | ^^^^^^^^ + | + = help: enable all of these features + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca_adts/none-incomplete.rs b/tests/ui/const-generics/gca_adts/none-incomplete.rs new file mode 100644 index 0000000000000..76078a42fa08a --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none-incomplete.rs @@ -0,0 +1,21 @@ +//! This test file ought to be part of `none.rs`, but, type-relative paths are difficult + +#![feature(gca_adts, adt_const_params)] + +use std::gca; +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum MyOption { + MySome, + MyNone, +} + +use MyOption::*; + +struct Struct; + +fn main() { + let _: Struct::MyNone)>; + //~^ ERROR complex const arguments must be placed inside of a `const` block +} diff --git a/tests/ui/const-generics/gca_adts/none-incomplete.stderr b/tests/ui/const-generics/gca_adts/none-incomplete.stderr new file mode 100644 index 0000000000000..bf8c538207579 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none-incomplete.stderr @@ -0,0 +1,8 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/none-incomplete.rs:19:24 + | +LL | let _: Struct::MyNone)>; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca_adts/none.rs b/tests/ui/const-generics/gca_adts/none.rs new file mode 100644 index 0000000000000..223f01d81a5a8 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none.rs @@ -0,0 +1,21 @@ +//@check-pass + +#![feature(gca_adts, adt_const_params)] + +use std::gca; +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum MyOption { + MySome, + MyNone, +} + +use MyOption::*; + +struct Struct; + +fn main() { + let _: Struct; + let _: Struct; +} diff --git a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs index b4fe7a9a5da2a..0053db1608ea4 100644 --- a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs +++ b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs @@ -3,11 +3,12 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature( + const_param_ty_trait, + gca_adts, gca_min_const_items, generic_const_parameter_types, inherent_associated_types, - min_adt_const_params, - const_param_ty_trait + min_adt_const_params )] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs index 112cf5563a59e..cd90cc6f66b99 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index 96f8461b9cb82..70ed0cbc41f64 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/adt_expr_arg_simple.rs:31:35 + --> $DIR/adt_expr_arg_simple.rs:30:35 | LL | foo::<{ gca!(Some:: { 0: N + 1 }) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/adt_expr_arg_simple.rs:36:38 + --> $DIR/adt_expr_arg_simple.rs:35:38 | LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs index c488b90aec14b..c9652b1c83385 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs @@ -1,10 +1,10 @@ #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs index 20bac03fab1c0..5bcfea9246066 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs @@ -1,26 +1,27 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![crate_type = "lib"] // Miscellaneous assortment of invalid cases of directly represented // `ConstArgKind::Struct`'s under mgca. #[derive(Eq, PartialEq, std::marker::ConstParamTy)] -struct Foo { field: T } +struct Foo { + field: T, +} fn NonStruct() {} fn accepts>() {} fn bar() { - accepts::<{ Foo:: { }}>(); + accepts::<{ Foo:: {} }>(); //~^ ERROR: struct expression with missing field initialiser for `field` - accepts::<{ Foo:: { field: const { 1 }, field: const { 2} }}>(); + accepts::<{ Foo:: { field: const { 1 }, field: const { 2 } } }>(); //~^ ERROR: struct expression with multiple initialisers for `field` - accepts::<{ Fooo:: { field: const { 1 } }}>(); + accepts::<{ Fooo:: { field: const { 1 } } }>(); //~^ ERROR: cannot find struct, variant or union type `Fooo` in this scope //~| ERROR: struct expression with invalid base path - accepts::<{ NonStruct { }}>(); + accepts::<{ NonStruct {} }>(); //~^ ERROR: cannot find struct, variant or union type `NonStruct` in this scope //~| ERROR: struct expression with invalid base path } diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr index 370a73b5a4bc6..707cfa1b73b31 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr @@ -1,51 +1,51 @@ error[E0422]: cannot find struct, variant or union type `Fooo` in this scope - --> $DIR/adt_expr_erroneuous_inits.rs:20:17 + --> $DIR/adt_expr_erroneuous_inits.rs:21:17 | -LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); +LL | accepts::<{ Fooo:: { field: const { 1 } } }>(); | ^^^^ not found in this scope | note: similarly named struct `Foo` defined here - --> $DIR/adt_expr_erroneuous_inits.rs:9:1 + --> $DIR/adt_expr_erroneuous_inits.rs:8:1 | -LL | struct Foo { field: T } +LL | struct Foo { | ^^^^^^^^^^^^^ help: a struct with a similar name exists | -LL - accepts::<{ Fooo:: { field: const { 1 } }}>(); -LL + accepts::<{ Foo:: { field: const { 1 } }}>(); +LL - accepts::<{ Fooo:: { field: const { 1 } } }>(); +LL + accepts::<{ Foo:: { field: const { 1 } } }>(); | error[E0574]: cannot find struct, variant or union type `NonStruct` in this scope - --> $DIR/adt_expr_erroneuous_inits.rs:23:17 + --> $DIR/adt_expr_erroneuous_inits.rs:24:17 | -LL | accepts::<{ NonStruct { }}>(); +LL | accepts::<{ NonStruct {} }>(); | ^^^^^^^^^ not found in this scope | = note: a function named `NonStruct` exists in another namespace error: struct expression with missing field initialiser for `field` - --> $DIR/adt_expr_erroneuous_inits.rs:16:17 + --> $DIR/adt_expr_erroneuous_inits.rs:17:17 | -LL | accepts::<{ Foo:: { }}>(); - | ^^^^^^^^^^^^^ +LL | accepts::<{ Foo:: {} }>(); + | ^^^^^^^^^^^^ error: struct expression with multiple initialisers for `field` - --> $DIR/adt_expr_erroneuous_inits.rs:18:49 + --> $DIR/adt_expr_erroneuous_inits.rs:19:49 | -LL | accepts::<{ Foo:: { field: const { 1 }, field: const { 2} }}>(); - | ^^^^^^^^^^^^^^^^^ +LL | accepts::<{ Foo:: { field: const { 1 }, field: const { 2 } } }>(); + | ^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path - --> $DIR/adt_expr_erroneuous_inits.rs:20:17 + --> $DIR/adt_expr_erroneuous_inits.rs:21:17 | -LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); +LL | accepts::<{ Fooo:: { field: const { 1 } } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path - --> $DIR/adt_expr_erroneuous_inits.rs:23:17 + --> $DIR/adt_expr_erroneuous_inits.rs:24:17 | -LL | accepts::<{ NonStruct { }}>(); - | ^^^^^^^^^^^^^ +LL | accepts::<{ NonStruct {} }>(); + | ^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs index 38eb04760c598..f4b59aaa1404e 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct S1 { diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr index 81f7c5366b461..dea156db19c14 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr @@ -1,41 +1,41 @@ error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:24:19 + --> $DIR/adt_expr_fields_type_check.rs:23:19 | LL | accepts_1::<{ S1:: { f1: N, f2: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `isize` - --> $DIR/adt_expr_fields_type_check.rs:24:19 + --> $DIR/adt_expr_fields_type_check.rs:23:19 | LL | accepts_1::<{ S1:: { f1: N, f2: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool` error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:27:19 + --> $DIR/adt_expr_fields_type_check.rs:26:19 | LL | accepts_2::<{ S2::(N, N) }>(); | ^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `isize` - --> $DIR/adt_expr_fields_type_check.rs:27:19 + --> $DIR/adt_expr_fields_type_check.rs:26:19 | LL | accepts_2::<{ S2::(N, N) }>(); | ^^^^^^^^^^^^^^ expected `isize`, found `bool` error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:30:19 + --> $DIR/adt_expr_fields_type_check.rs:29:19 | LL | accepts_3::<{ En::Var1::(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `i64` - --> $DIR/adt_expr_fields_type_check.rs:32:19 + --> $DIR/adt_expr_fields_type_check.rs:31:19 | LL | accepts_3::<{ En::Var2:: { field: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found `bool` error[E0308]: mismatched types - --> $DIR/adt_expr_fields_type_check.rs:34:51 + --> $DIR/adt_expr_fields_type_check.rs:33:51 | LL | accepts_3::<{ En::Var2:: { field: const { false } } }>(); | ^^^^^ expected `i64`, found `bool` diff --git a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs index 30b8ca3dd2752..13feedadbcfd7 100644 --- a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs +++ b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs @@ -1,14 +1,14 @@ //@ check-pass #![feature( - generic_const_items, - gca_min_const_items, - gca_macroless_args, adt_const_params, - generic_const_parameter_types, - const_param_ty_trait + const_param_ty_trait, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_items, + generic_const_parameter_types )] -#![expect(incomplete_features)] use std::gca; use std::marker::{ConstParamTy, ConstParamTy_, PhantomData}; diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs index d48b5cb9e7100..7cc24d660d04c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs @@ -1,13 +1,13 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] enum E { - S {} + S {}, } fn foo() {} fn main() { - foo::<{E::S { x: const { 1 } }}>(); - //~^ ERROR variant `E::S` has no field named `x` [E0559] + foo::<{ E::S { x: const { 1 } } }>(); + //~^ ERROR variant `E::S` has no field named `x` [E0559] } diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr index 7ac3b28cdca5b..8d201a2b8943c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr @@ -1,8 +1,8 @@ error[E0559]: variant `E::S` has no field named `x` - --> $DIR/adt_expr_unit_enum_extra_field.rs:11:19 + --> $DIR/adt_expr_unit_enum_extra_field.rs:11:20 | -LL | foo::<{E::S { x: const { 1 } }}>(); - | ^ `E::S` does not have this field +LL | foo::<{ E::S { x: const { 1 } } }>(); + | ^ `E::S` does not have this field error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs index 0eaadd1a9b31d..68a1600e218eb 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs @@ -1,4 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs index 134a82e9d3490..59587c0093295 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -2,9 +2,14 @@ //! //! Ensure that providing an array const arg with the wrong number of elements //! doesn't ICE or silently cause UB. -#![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] -#![feature(unsized_const_params, generic_const_parameter_types)] +#![feature( + adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_parameter_types, + unsized_const_params +)] use std::gca; use std::marker::ConstParamTy_; diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr index 72c2a367c7246..c0625e737d307 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr @@ -1,59 +1,59 @@ error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:31:11 + --> $DIR/array-const-arg-len-mismatch.rs:36:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:12:42 + --> $DIR/array-const-arg-len-mismatch.rs:17:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b"\x00\x00\x00"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:33:11 + --> $DIR/array-const-arg-len-mismatch.rs:38:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:12:42 + --> $DIR/array-const-arg-len-mismatch.rs:17:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:35:13 + --> $DIR/array-const-arg-len-mismatch.rs:40:13 | LL | bar::<{ [] }>(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:16:8 + --> $DIR/array-const-arg-len-mismatch.rs:21:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"\x01\x02\x03"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:37:13 + --> $DIR/array-const-arg-len-mismatch.rs:42:13 | LL | bar::<{ [1, 2, 3] }>(); | ^^^^^^^^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:16:8 + --> $DIR/array-const-arg-len-mismatch.rs:21:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"*"` is not of type `[u8; 3]` - --> $DIR/array-const-arg-len-mismatch.rs:39:13 + --> $DIR/array-const-arg-len-mismatch.rs:44:13 | LL | baz::<{ [42] }>(); | ^^^^ expected `[u8; 3]`, found `[u8; 1]` | note: required by a const generic parameter in `baz` - --> $DIR/array-const-arg-len-mismatch.rs:28:8 + --> $DIR/array-const-arg-len-mismatch.rs:33:8 | LL | fn baz::LEN]>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `baz` diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs index def077e4d292d..a6d1acb773a23 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs @@ -1,5 +1,4 @@ -#![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] use std::marker::ConstParamTy; #[derive(Eq, PartialEq, ConstParamTy)] diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr index 573620366cbce..f8b9a3c9cee37 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr @@ -1,5 +1,5 @@ error: the constant `Bar` is not of type `Foo` - --> $DIR/array-const-arg-type-mismatch.rs:13:14 + --> $DIR/array-const-arg-type-mismatch.rs:12:14 | LL | test::<{ [Bar] }>(); | ^^^^^ expected `Foo`, found `Bar` diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr index 2e3b2172b7325..43a8312a21dbd 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:13:33 + --> $DIR/array-expr-complex.rs:12:33 | LL | takes_array::<{ gca!([1, 2, 1 + 2]) }>(); | ^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr index 2b25efb6ab090..ed9e7d184c023 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:16:26 + --> $DIR/array-expr-complex.rs:15:26 | LL | takes_array::<{ gca!([X; 3]) }>(); | ^^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr index 09515bafa7025..e67703aab474f 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:19:26 + --> $DIR/array-expr-complex.rs:18:26 | LL | takes_array::<{ gca!([0; Y]) }>(); | ^^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.rs b/tests/ui/const-generics/mgca/array-expr-complex.rs index 1c96c492b3cfd..12104e5c5bd08 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.rs +++ b/tests/ui/const-generics/mgca/array-expr-complex.rs @@ -1,7 +1,6 @@ //@ revisions: r1 r2 r3 -#![expect(incomplete_features)] -#![feature(gca_min_const_items, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array-expr-simple.rs b/tests/ui/const-generics/mgca/array-expr-simple.rs index eba86898c41a1..d9436afb6015d 100644 --- a/tests/ui/const-generics/mgca/array-expr-simple.rs +++ b/tests/ui/const-generics/mgca/array-expr-simple.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array_u32() {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs index a7582258de2f5..fe1641ff38b2f 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs @@ -1,7 +1,5 @@ //! regression test for -#![feature(gca_min_const_items, gca_macroless_args)] -#![feature(adt_const_params)] -#![expect(incomplete_features)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] trait Trait1 {} trait Trait2 {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr index 169282547fc1d..f930849466eae 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr @@ -1,11 +1,11 @@ error: expected `usize`, found const array - --> $DIR/array-expr-type-mismatch-in-where-bound.rs:11:17 + --> $DIR/array-expr-type-mismatch-in-where-bound.rs:9:17 | LL | T: Trait1<{ [] }>, | ^^ error: type annotations needed for the literal - --> $DIR/array-expr-type-mismatch-in-where-bound.rs:17:15 + --> $DIR/array-expr-type-mismatch-in-where-bound.rs:15:15 | LL | T: Trait2<3>, | ^ diff --git a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs index 85ef64c498a4c..5b22ff101030b 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array() {} diff --git a/tests/ui/const-generics/mgca/array-expr-with-macro.rs b/tests/ui/const-generics/mgca/array-expr-with-macro.rs index db768339118f3..bf586b90a8e5a 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-macro.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-macro.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] macro_rules! make_array { diff --git a/tests/ui/const-generics/mgca/array-expr-with-struct.rs b/tests/ui/const-generics/mgca/array-expr-with-struct.rs index 1d4c051e53f0b..bdc7b6009ea04 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-struct.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-struct.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs index f429ca20ce832..a4749c63f3a8a 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs @@ -1,11 +1,11 @@ //@ run-pass #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] #![allow(dead_code)] fn takes_tuple() {} diff --git a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs index a4131a22337aa..624484c4d1467 100644 --- a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs +++ b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs index aa6385c28ded0..7b5f3747f5a58 100644 --- a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs @@ -1,10 +1,10 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - generic_const_parameter_types, + gca_adts, + gca_macroless_args, gca_min_const_items, - gca_macroless_args + generic_const_parameter_types )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs index 7edeb25f30e48..308ba90d72646 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr index b044775b80c94..fd963a5055d0e 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:15:30 + --> $DIR/array_expr_arg_complex.rs:14:30 | LL | takes_array::<{ gca!([N, N + 1]) }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:16:42 + --> $DIR/array_expr_arg_complex.rs:15:42 | LL | takes_tuple_with_array::<{ gca!(([N, N + 1], N)) }>(); | ^^^^^ diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs index 9642a066ad32b..258160017f179 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -1,15 +1,18 @@ -#![feature(gca_min_const_items)] -#![feature(adt_const_params, unsized_const_params)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, unsized_const_params)] + use std::gca; + #[derive(PartialEq, Eq, std::marker::ConstParamTy)] pub enum Enum { Unit, Tuple(), Store(T), } + pub mod module { pub use super::Enum::Store; } + fn main() { const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); //~^ ERROR: type arguments are not allowed on unit variant `Unit` [E0109] diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr index 02903379932ae..c9d8033d15b68 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr @@ -1,5 +1,5 @@ error[E0109]: type arguments are not allowed on unit variant `Unit` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:14:49 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:17:49 | LL | const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); | ---- ^^ type argument not allowed @@ -14,7 +14,7 @@ LL + const _: Enum<()> = gca!(Enum::<()>::Unit); | error[E0109]: type arguments are not allowed on tuple variant `Tuple` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:16:50 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:19:50 | LL | const _: Enum<()> = gca!(Enum::<()>::Tuple::<()>()); | ----- ^^ type argument not allowed @@ -29,7 +29,7 @@ LL + const _: Enum<()> = gca!(Enum::<()>::Tuple()); | error[E0109]: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:18:37 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:21:37 | LL | const _: Enum<()> = gca!(self::::Enum::<()>::Store); | ---- ^^^ type argument not allowed diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs index f89dd4b87f32a..b705e695754da 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -1,7 +1,6 @@ //@ check-pass -#![feature(gca_min_const_items)] -#![feature(adt_const_params, unsized_const_params)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs index 009722fbe93a5..2377a3051307c 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs @@ -1,7 +1,11 @@ //! Regression test for #160553 (used to ICE) -#![allow(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] -#![feature(generic_const_parameter_types)] +#![feature( + adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_parameter_types +)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr index 4906b05939900..08c115d5dedb5 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr @@ -1,11 +1,11 @@ error: the constant `*b"\x01\x02\x03"` is not of type `[u8; ::LEN]` - --> $DIR/generic_const_items-mismatched-array-len.rs:23:11 + --> $DIR/generic_const_items-mismatched-array-len.rs:27:11 | LL | foo::() | ^ expected `[u8; ::LEN]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/generic_const_items-mismatched-array-len.rs:18:18 + --> $DIR/generic_const_items-mismatched-array-len.rs:22:18 | LL | fn foo::LEN]>() -> [u8; ::LEN] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs index 075237a2094b5..bdf7a50bd3041 100644 --- a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, gca_min_const_items, generic_const_parameter_types)] +#![feature(min_adt_const_params, gca_adts, gca_min_const_items, generic_const_parameter_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs index aecd2b81b1c02..5563d35bb92af 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -1,11 +1,11 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - generic_const_items, - generic_const_parameter_types, + const_param_ty_trait, + gca_adts, gca_min_const_items, - const_param_ty_trait + generic_const_items, + generic_const_parameter_types )] use std::gca; diff --git a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs index 69c45462fb011..80bfe0d13b35e 100644 --- a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs +++ b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs index 995f715984d54..3654a2c6ff249 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs @@ -2,8 +2,7 @@ //! things that must be an anon const, are currently less than ideal. This test merely asserts the //! current (bad) state of diagnostics, so we can track improvements over time. -#![feature(gca_min_const_items, min_adt_const_params)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, min_adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr index 4d5f071037f97..744014bb18ca5 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:15:20 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:14:20 | LL | f::<{ gca!((N, 1 + 1)) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:13:12 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:12:12 | LL | f::<{ (N, 1 + 1) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs index c5f3a6caeb112..5680e0fffe5f9 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs index 6888a45c3bd3f..d35971802e7f2 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs @@ -1,8 +1,7 @@ //! Regression test for //@ edition: 2024 -#![allow(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, core::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr index 0184aebf157ae..9087f98cbb3f4 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr @@ -1,29 +1,29 @@ error: the constant `Option::::Some(N)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:18:13 + --> $DIR/printing_valtrees_supports_non_values.rs:17:13 | LL | foo::<{ Option::Some:: { 0: N } }>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `Option::::Some(::ASSOC)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:23:13 + --> $DIR/printing_valtrees_supports_non_values.rs:22:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/printing_valtrees_supports_non_values.rs:30:5 + --> $DIR/printing_valtrees_supports_non_values.rs:29:5 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` @@ -34,25 +34,25 @@ LL | fn test_ice_missing_bound() { | +++++++ error: the constant `Option::::Some(_)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:30:13 + --> $DIR/printing_valtrees_supports_non_values.rs:29:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `Option::::Some(_)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:36:13 + --> $DIR/printing_valtrees_supports_non_values.rs:35:13 | LL | foo::<{ Option::Some:: { 0: _ } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs index 9a4d4ca05be33..115b32d91ea46 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs @@ -1,6 +1,5 @@ //! regression test for -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] fn foo() { [0; size_of::<*mut T>()]; diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index 1abfff9518f44..2d725d66fcdc4 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -1,17 +1,17 @@ error: function items cannot be used as const args - --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 + --> $DIR/size-of-generic-ptr-in-array-len.rs:5:9 | LL | [0; size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 + --> $DIR/size-of-generic-ptr-in-array-len.rs:5:9 | LL | [0; size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^^^ error: generic parameters may not be used in const operations - --> $DIR/size-of-generic-ptr-in-array-len.rs:9:32 + --> $DIR/size-of-generic-ptr-in-array-len.rs:8:32 | LL | [0; const { size_of::<*mut T>() }]; | ^ diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs index f14309f7492f4..9cca963a13f00 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs @@ -1,8 +1,7 @@ // This test ensures proper diagnostics emission during HIR ty lowering // See https://github.com/rust-lang/rust/issues/153254 -#![feature(gca_min_const_items)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, min_adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr index 3d09bbdab6072..73f0e76498770 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr @@ -1,11 +1,11 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/syntactic-type-mismatch.rs:9:11 + --> $DIR/syntactic-type-mismatch.rs:8:11 | LL | const T0: _ = gca!(()); | ^ not allowed in type signatures error: missing type for `const` item - --> $DIR/syntactic-type-mismatch.rs:12:9 + --> $DIR/syntactic-type-mismatch.rs:11:9 | LL | const T1 = gca!([0]); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs index da66ce8195d0f..318bf82691316 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs index 42ebe44172b05..f16106cd798d0 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index 925572c27cb0b..e3f6b3b8834b2 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_ctor_complex_args.rs:13:31 + --> $DIR/tuple_ctor_complex_args.rs:12:31 | LL | with_point::<{ gca!(Point(N + 1, N)) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_ctor_complex_args.rs:16:34 + --> $DIR/tuple_ctor_complex_args.rs:15:34 | LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index db158f3f38b00..6e720aba1b4ac 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index 56b11b2894aa2..b9bbfcc37469d 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope - --> $DIR/tuple_ctor_erroneous.rs:30:23 + --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^ not found in this scope @@ -10,61 +10,61 @@ LL | fn test_errors() { | +++++++++++++++++++++++++++++++++++ error: tuple constructor has 2 arguments but 1 were provided - --> $DIR/tuple_ctor_erroneous.rs:24:23 + --> $DIR/tuple_ctor_erroneous.rs:23:23 | LL | accepts_point::<{ Point(N) }>(); | ^^^^^^^^ error: tuple constructor has 2 arguments but 3 were provided - --> $DIR/tuple_ctor_erroneous.rs:27:23 + --> $DIR/tuple_ctor_erroneous.rs:26:23 | LL | accepts_point::<{ Point(N, N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:30:23 + --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^ error: function items cannot be used as const args - --> $DIR/tuple_ctor_erroneous.rs:34:23 + --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:34:23 + --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:38:23 + --> $DIR/tuple_ctor_erroneous.rs:37:23 | LL | accepts_point::<{ CONST_ITEM(N, N) }>(); | ^^^^^^^^^^^^^^^^ error: the constant `Point` is not of type `Point` - --> $DIR/tuple_ctor_erroneous.rs:41:23 + --> $DIR/tuple_ctor_erroneous.rs:40:23 | LL | accepts_point::<{ Point }>(); | ^^^^^ expected `Point`, found struct constructor | note: required by a const generic parameter in `accepts_point` - --> $DIR/tuple_ctor_erroneous.rs:18:18 + --> $DIR/tuple_ctor_erroneous.rs:17:18 | LL | fn accepts_point() {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point` error: the constant `MyEnum::::Variant` is not of type `MyEnum` - --> $DIR/tuple_ctor_erroneous.rs:44:22 + --> $DIR/tuple_ctor_erroneous.rs:43:22 | LL | accepts_enum::<{ MyEnum::Variant:: }>(); | ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum`, found enum constructor | note: required by a const generic parameter in `accepts_enum` - --> $DIR/tuple_ctor_erroneous.rs:19:17 + --> $DIR/tuple_ctor_erroneous.rs:18:17 | LL | fn accepts_enum>() {} | ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum` diff --git a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs index 096f56d9512a8..e03db5d7b0fdc 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs index 6a5c28bca6898..eaa1744bc5bbd 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs index 50abdd97e908f..53216e3c5c14b 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] struct Y { stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found `([1, 2], 3, [4, 5])` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr index aa54a5ae77048..098a676d6d918 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr @@ -1,5 +1,5 @@ error: expected `usize`, found `([1, 2], 3, [4, 5])` - --> $DIR/tuple_expr_arg_bad-issue-151048.rs:5:19 + --> $DIR/tuple_expr_arg_bad-issue-151048.rs:4:19 | LL | stuff: [u8; { ([1, 2], 3, [4, 5]) }], | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs index 2b39a8b585faf..ff73b128fd522 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index e6f004b2f9d68..cdee5ff343ba3 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -1,23 +1,23 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:15:30 + --> $DIR/tuple_expr_arg_complex.rs:14:30 | LL | takes_tuple::<{ gca!((N, N + 1)) }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:16:30 + --> $DIR/tuple_expr_arg_complex.rs:15:30 | LL | takes_tuple::<{ gca!((N, T::ASSOC + 1)) }>(); | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:18:41 + --> $DIR/tuple_expr_arg_complex.rs:17:41 | LL | takes_nested_tuple::<{ gca!((N, (N, N + 1))) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_expr_arg_complex.rs:19:49 + --> $DIR/tuple_expr_arg_complex.rs:18:49 | LL | takes_nested_tuple::<{ gca!((N, (N, const { N + 1 }))) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs index 2b67665d7281b..685d29ed4cec1 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs @@ -1,12 +1,12 @@ //@ check-pass #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs index 780b757c0df1c..5247fcdec0e2f 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] pub fn takes_nested_tuple() { takes_nested_tuple::<{ () }> //~ ERROR expected `u32`, found `()` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr index d8314a6b6a57e..a45ca91d69e3c 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr @@ -1,5 +1,5 @@ error: expected `u32`, found `()` - --> $DIR/tuple_expr_arg_mismatch_type.rs:5:28 + --> $DIR/tuple_expr_arg_mismatch_type.rs:4:28 | LL | takes_nested_tuple::<{ () }> | ^^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs index 8c4f64adf34dc..315636bc2e75d 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs @@ -1,7 +1,6 @@ //@ check-pass -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs index 7d8a1a1264bd9..c1c118d575a69 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs @@ -1,4 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] // Regression test for an ICE in privacy checking while walking the `T` qself // of `T::ASSOC` inside a tuple const argument. diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs index e67a5a0a72e54..04533b8d96455 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs @@ -1,9 +1,9 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs index 46c661cfb96ce..e7f396543e66d 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs @@ -1,9 +1,13 @@ // Regression test for https://github.com/rust-lang/rust/issues/154632 -#![feature(generic_const_exprs)] -#![feature(gca_min_const_items)] -#![feature(gca_macroless_args)] -#![feature(generic_const_items)] +#![feature( + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_exprs, + generic_const_items, + min_adt_const_params +)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr index 623ae087687f5..7135773752b55 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr @@ -1,5 +1,5 @@ error[E0573]: cannot find type `ADD1` in this scope - --> $DIR/type_const-adt-expr-missing-field.rs:12:22 + --> $DIR/type_const-adt-expr-missing-field.rs:16:22 | LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^ not found in this scope @@ -7,7 +7,7 @@ LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); = note: a constant named `ADD1` exists in another namespace error: unconstrained generic constant - --> $DIR/type_const-adt-expr-missing-field.rs:10:1 + --> $DIR/type_const-adt-expr-missing-field.rs:14:1 | LL | const ADD1: usize = gca!(const { N + 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | const ADD1: usize where [(); const { N + 1 }]: = gca!(const | ++++++++++++++++++++++++++++ error: struct expression with missing field initialiser for `0` - --> $DIR/type_const-adt-expr-missing-field.rs:12:43 + --> $DIR/type_const-adt-expr-missing-field.rs:16:43 | LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr index 46be38bb1a53d..aac10bc622b5d 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr @@ -1,53 +1,53 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:13:1 + --> $DIR/type_const-generic-param-in-type.rs:18:1 | LL | const FOO: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:16:1 + --> $DIR/type_const-generic-param-in-type.rs:21:1 | LL | const BAR: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:19:1 + --> $DIR/type_const-generic-param-in-type.rs:24:1 | LL | const BAZ<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:37:5 + --> $DIR/type_const-generic-param-in-type.rs:42:5 | LL | const ASSOC: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:40:5 + --> $DIR/type_const-generic-param-in-type.rs:45:5 | LL | const ASSOC_CONST: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:43:5 + --> $DIR/type_const-generic-param-in-type.rs:48:5 | LL | const ASSOC_LT<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:24:5 + --> $DIR/type_const-generic-param-in-type.rs:29:5 | LL | const ASSOC: [T; 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:28:5 + --> $DIR/type_const-generic-param-in-type.rs:33:5 | LL | const ASSOC_CONST: StructWithConstParam; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:32:5 + --> $DIR/type_const-generic-param-in-type.rs:37:5 | LL | const ASSOC_LT<'a>: [&'a (); 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs index 80293325d8800..b64853f37bb8f 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs @@ -1,7 +1,12 @@ //@ revisions: nogate gate //@ [gate] check-pass -#![expect(incomplete_features)] -#![feature(adt_const_params, unsized_const_params, gca_min_const_items, generic_const_items)] +#![feature( + adt_const_params, + gca_adts, + gca_min_const_items, + generic_const_items, + unsized_const_params +)] #![cfg_attr(gate, feature(generic_const_parameter_types))] use std::gca; diff --git a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs index a80f602fbf96a..c3ba68ae5213d 100644 --- a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args, gca_adts)] struct ArrWrap; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs index f5d3c06d7bc8e..3ca3c9bcb7536 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs @@ -1,7 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] struct TakesArr; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr index a2e212b28ec6f..3e2ee8c5f718a 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong_type_const_arr_diag.rs:9:32 + --> $DIR/wrong_type_const_arr_diag.rs:8:32 | LL | let _: TakesArr<{ [N] }> = TakesArr::<{ [1] }>; | ----------------- ^^^^^^^^^^^^^^^^^^^ expected `[N]`, found `*b"\x01"` diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs index 225d3ef226cba..ee91819204859 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs @@ -1,7 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr index 66de4a4d6a864..5338a7bfbd973 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong_type_const_arr_diag_trait.rs:17:51 + --> $DIR/wrong_type_const_arr_diag_trait.rs:16:51 | LL | let _: TakesArr<{ [::ASSOC] }> = TakesArr::<{ [1] }>; | ------------------------------------ ^^^^^^^^^^^^^^^^^^^ expected `[::ASSOC]`, found `*b"\x01"` diff --git a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs index 675cecc68f884..e6d8e362dd191 100644 --- a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs +++ b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(min_adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] struct S; diff --git a/tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs b/tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs new file mode 100644 index 0000000000000..421b9a512c1e4 --- /dev/null +++ b/tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs @@ -0,0 +1,37 @@ +//! Regression tests for . When checking whether +//! method receivers for a trait `Trait` are dynamically dispatchable, we use a placeholder type in +//! place of `dyn Trait` to avoid a cycle (as that would require determining whether `Trait` is dyn- +//! compatible). This placeholder must satisfy `Trait`'s where-bounds to avoid errors in param- +//! environment normalization. +//@ check-pass + +// Test 1 + +use std::ops::Deref; + +trait SignatureToFnPtr { + type Ptr; +} + +trait DerefsToFn +where + (Args, Self::Output): SignatureToFnPtr, + Self: Deref::Ptr>, +{ + type Output; + fn method(&self); +} + +// Test 2 + +trait Associator { + type Point; +} + +trait Marker {} + +trait Trait + ?Sized>: Marker { + fn method(&self); +} + +fn main() {} diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs index cfafca68bfd2f..188f63fa94bab 100644 --- a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs @@ -26,6 +26,8 @@ where //~| ERROR the size for values of type `Self` cannot be known //~| ERROR type mismatch resolving //~| ERROR the size for values of type `Self` cannot be known + //~| ERROR type mismatch resolving + //~| ERROR the size for values of type `RustaceansAreAwesome` cannot be known } trait Mirror { diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr index b8796f673f4a5..06fd8bced4af1 100644 --- a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr @@ -5,11 +5,29 @@ LL | fn transmute(&self, t: T) -> ::Assoc; | ^ not found in this scope error[E0601]: `main` function not found in crate `ice_generics_of_crate_root_152335` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:57 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:57 | LL | impl> Mirror for T {} | ^ consider adding a `main` function to `$DIR/ice-generics-of-crate-root-152335.rs` +error[E0271]: type mismatch resolving `>::Assoc == RustaceansAreAwesome` + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 + | +LL | fn transmute(&self, t: T) -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `RustaceansAreAwesome`, found type parameter `T` + | + = note: expected type parameter `RustaceansAreAwesome` + found type parameter `T` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 + | +LL | impl> Mirror for T {} + | --------- ^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + error[E0271]: type mismatch resolving `>::Assoc == Self` --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | @@ -21,13 +39,27 @@ LL | fn transmute(&self, t: T) -> ::Assoc; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ | | | unsatisfied trait bound introduced here +error[E0277]: the size for values of type `RustaceansAreAwesome` cannot be known at compilation time + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 + | +LL | fn transmute(&self, t: T) -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 + | +LL | impl> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here + error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | @@ -35,7 +67,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -69,7 +101,7 @@ LL | trait Foo: Super = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -83,7 +115,7 @@ LL | trait Foo: Super | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -95,7 +127,7 @@ LL | trait Foo: Super + Sized | +++++++ error[E0046]: not all trait items implemented, missing: `Assoc` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:1 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:1 | LL | type Assoc: ?Sized; | ------------------ `Assoc` from trait @@ -120,7 +152,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -134,7 +166,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -145,7 +177,7 @@ help: consider further restricting `Self` LL | fn transmute(&self, t: T) -> ::Assoc where Self: Sized; | +++++++++++++++++ -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0038, E0046, E0271, E0277, E0405, E0601. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.rs b/tests/ui/feature-gates/feature-gate-gca-adts.rs new file mode 100644 index 0000000000000..6b77771fc4cdc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.rs @@ -0,0 +1,24 @@ +//@ revisions: without without_with_min_items with +//@[with] check-pass + +#![feature(min_adt_const_params)] +#![cfg_attr(with, feature(gca_adts))] +// gca_min_const_items enables the gca! macro as well, which is vaguely interesting to test too +#![cfg_attr(without_with_min_items, feature(gca_min_const_items))] + +use std::gca; +//[without]~^ ERROR use of unstable library feature `gca_min_const_items` + +struct S; + +fn main() { + let _: S = S::; + //[without_with_min_items]~^ ERROR complex const arguments must be placed inside of a `const` block + //[without_with_min_items]~| ERROR complex const arguments must be placed inside of a `const` block + //[without]~^^^ ERROR use of unstable library feature `gca_min_const_items` + //[without]~| ERROR use of unstable library feature `gca_min_const_items` + //[without]~| ERROR expected type, found `gca!()` constant + //[without]~| ERROR expected type, found `gca!()` constant + //[without]~| ERROR type provided when a constant was expected + //[without]~| ERROR type provided when a constant was expected +} diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr b/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr new file mode 100644 index 0000000000000..9076e2313db09 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr @@ -0,0 +1,58 @@ +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: expected type, found `gca!()` constant + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error: expected type, found `gca!()` constant + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:9:5 + | +LL | use std::gca; + | ^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr b/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr new file mode 100644 index 0000000000000..84c64b828b3fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr @@ -0,0 +1,14 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/feature-gate-gca-adts.rs:15:19 + | +LL | let _: S = S::; + | ^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/feature-gate-gca-adts.rs:15:39 + | +LL | let _: S = S::; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/imports/auxiliary/macro-generated-extern-crate.rs b/tests/ui/imports/auxiliary/macro-generated-extern-crate.rs new file mode 100644 index 0000000000000..8a2c17266b7a9 --- /dev/null +++ b/tests/ui/imports/auxiliary/macro-generated-extern-crate.rs @@ -0,0 +1,3 @@ +pub trait MyTrait { + fn custom() {} +} diff --git a/tests/ui/imports/macro-generated-extern-crate.rs b/tests/ui/imports/macro-generated-extern-crate.rs new file mode 100644 index 0000000000000..a7b87efdd8fbe --- /dev/null +++ b/tests/ui/imports/macro-generated-extern-crate.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 +//@ aux-build: macro-generated-extern-crate.rs + +const _: () = { + extern crate macro_generated_extern_crate as _my_crate; + impl _my_crate::MyTrait for Local {} +}; + +struct Local; + +fn main() { + Local::custom(); + //~^ ERROR no associated function or constant named `custom` found for struct `Local` +} diff --git a/tests/ui/imports/macro-generated-extern-crate.stderr b/tests/ui/imports/macro-generated-extern-crate.stderr new file mode 100644 index 0000000000000..e103b185789ac --- /dev/null +++ b/tests/ui/imports/macro-generated-extern-crate.stderr @@ -0,0 +1,18 @@ +error[E0599]: no associated function or constant named `custom` found for struct `Local` in the current scope + --> $DIR/macro-generated-extern-crate.rs:12:12 + | +LL | struct Local; + | ------------ associated function or constant `custom` not found for this struct +... +LL | Local::custom(); + | ^^^^^^ associated function or constant not found in `Local` + | + = help: items from traits can only be used if the trait is in scope +help: trait `MyTrait` which provides `custom` is implemented but not in scope; perhaps you want to import it + | +LL + use macro_generated_extern_crate::MyTrait; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/shadowed-intrinsic-method-deref.stderr b/tests/ui/methods/shadowed-intrinsic-method-deref.stderr index 4e0c5dfc55f09..d4dccd6dc5fdb 100644 --- a/tests/ui/methods/shadowed-intrinsic-method-deref.stderr +++ b/tests/ui/methods/shadowed-intrinsic-method-deref.stderr @@ -6,7 +6,7 @@ LL | let sb : &S = &s.borrow(); | help: the trait `Borrow` is not implemented for `Rc>` but trait `Borrow>` is implemented for it - --> $SRC_DIR/alloc/src/rc.rs:LL:COL + --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL = help: for that trait implementation, expected `RefCell`, found `S` = note: there's an inherent method on `RefCell` of the same name, which can be auto-dereferenced from `&RefCell` help: to access the inherent method on `RefCell`, use the fully-qualified path diff --git a/tests/ui/never_type/basic/method-on-never.stderr b/tests/ui/never_type/basic/method-on-never.current.stderr similarity index 93% rename from tests/ui/never_type/basic/method-on-never.stderr rename to tests/ui/never_type/basic/method-on-never.current.stderr index f5903616be6f4..ec89b37bc403e 100644 --- a/tests/ui/never_type/basic/method-on-never.stderr +++ b/tests/ui/never_type/basic/method-on-never.current.stderr @@ -1,5 +1,5 @@ warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:42:7 + --> $DIR/method-on-never.rs:44:7 | LL | x.method(); | ^^^^^^ @@ -10,7 +10,7 @@ LL | x.method(); = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:46:17 + --> $DIR/method-on-never.rs:48:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -20,7 +20,7 @@ LL | { loop {} }.method(); = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:51:16 + --> $DIR/method-on-never.rs:53:16 | LL | y => y.method(), | ^^^^^^ @@ -30,7 +30,7 @@ LL | y => y.method(), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:57:27 + --> $DIR/method-on-never.rs:59:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | error => (&error).anyhow_kind().new(error), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:63:9 + --> $DIR/method-on-never.rs:65:9 | LL | res.method(); | ^^^^^^ @@ -53,7 +53,7 @@ warning: 5 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:42:7 + --> $DIR/method-on-never.rs:44:7 | LL | x.method(); | ^^^^^^ @@ -65,7 +65,7 @@ LL | x.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:46:17 + --> $DIR/method-on-never.rs:48:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -77,7 +77,7 @@ LL | { loop {} }.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:51:16 + --> $DIR/method-on-never.rs:53:16 | LL | y => y.method(), | ^^^^^^ @@ -89,7 +89,7 @@ LL | y => y.method(), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:57:27 + --> $DIR/method-on-never.rs:59:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | error => (&error).anyhow_kind().new(error), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:63:9 + --> $DIR/method-on-never.rs:65:9 | LL | res.method(); | ^^^^^^ diff --git a/tests/ui/never_type/basic/method-on-never.next.stderr b/tests/ui/never_type/basic/method-on-never.next.stderr new file mode 100644 index 0000000000000..ec89b37bc403e --- /dev/null +++ b/tests/ui/never_type/basic/method-on-never.next.stderr @@ -0,0 +1,113 @@ +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:44:7 + | +LL | x.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:48:17 + | +LL | { loop {} }.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:53:16 + | +LL | y => y.method(), + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:59:27 + | +LL | error => (&error).anyhow_kind().new(error), + | ^^^^^^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:65:9 + | +LL | res.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + +warning: 5 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:44:7 + | +LL | x.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:48:17 + | +LL | { loop {} }.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:53:16 + | +LL | y => y.method(), + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:59:27 + | +LL | error => (&error).anyhow_kind().new(error), + | ^^^^^^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:65:9 + | +LL | res.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = 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 #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + diff --git a/tests/ui/never_type/basic/method-on-never.rs b/tests/ui/never_type/basic/method-on-never.rs index 4194884ade9ea..ac928a0e9d071 100644 --- a/tests/ui/never_type/basic/method-on-never.rs +++ b/tests/ui/never_type/basic/method-on-never.rs @@ -1,3 +1,5 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver //@ check-pass // Regression test for https://github.com/rust-lang/rust/issues/143349 diff --git a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr index c408b747b506f..ff069320f413d 100644 --- a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr +++ b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -10,7 +10,7 @@ LL | A::deserialize(); = help: items from traits can only be used if the trait is in scope help: trait `Deserialize` which provides `deserialize` is implemented but not in scope; perhaps you want to import it | -LL + use ::deserialize::_a::Deserialize; +LL + use issue_87932_a::Deserialize; | error: aborting due to 1 previous error diff --git a/tests/ui/std/overflow-check-ops.rs b/tests/ui/std/overflow-check-ops.rs index 458c1b121664e..57db92610b20a 100644 --- a/tests/ui/std/overflow-check-ops.rs +++ b/tests/ui/std/overflow-check-ops.rs @@ -7,7 +7,6 @@ //@[WRAP] compile-flags: -C overflow-checks=false #![feature(cfg_overflow_checks)] -#![feature(funnel_shifts)] use std::hint::black_box as bb; use std::{assert_matches, fmt, panic}; diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index b8a240f7f07c5..e3d01bd588a4f 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -13,7 +13,7 @@ LL | let _: &[i8] = data.into(); `[T; 6]` implements `From<(T, T, T, T, T, T)>` `[T; 7]` implements `From<(T, T, T, T, T, T, T)>` `[T; 8]` implements `From<(T, T, T, T, T, T, T, T)>` - and 7 others + and 8 others = note: required for `&[u8]` to implement `Into<&[i8]>` error: aborting due to 1 previous error diff --git a/tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs b/tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs new file mode 100644 index 0000000000000..e774bef50c123 --- /dev/null +++ b/tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs @@ -0,0 +1,26 @@ +//! Regression test adjacent to +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +#![feature(const_trait_impl)] +#![feature(const_clone)] + +// At the time of writing, `ZERO` is evaluated in an environment containing `g`'s `(u8,): Clone` +// clause. In the new solver, this wasn't dropped in favor of the built-in `(u8,): Clone` impl when +// resolving an instance for `<(u8,) as Clone>::clone`, which resulted in ambiguity. + +const ZERO: (u8,) = (0,).clone(); + +fn g() +where + (u8,): Clone, +{ + match (0,) { + ZERO => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs b/tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs new file mode 100644 index 0000000000000..e2c27d4f90e11 --- /dev/null +++ b/tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs @@ -0,0 +1,29 @@ +//! Regression test for +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// At the time of writing, when resolving an instance for `::N`, the environment +// contains `f`'s `u8: Trait` clause. The old solver dropped the where clause candidate in favor of +// the `impl Trait for u8` candidate, but the new solver didn't, which resulted in ambiguity. + +pub trait Trait { + const N: usize; +} + +impl Trait for u8 { + const N: usize = 0; +} + +pub fn f() +where + u8: Trait, +{ + match 0 { + ::N => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/traits/bound/same-crate-name.rs b/tests/ui/traits/bound/same-crate-name.rs index acd4894612872..5de6620bf4856 100644 --- a/tests/ui/traits/bound/same-crate-name.rs +++ b/tests/ui/traits/bound/same-crate-name.rs @@ -32,15 +32,11 @@ fn main() { extern crate crate_a1 as a; a::try_foo(foo); //~^ ERROR E0277 - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `implements_no_traits` has no impl for `Foo` a::try_foo(implements_no_traits); //~^ ERROR E0277 - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `other_variant_implements_mismatched_trait` @@ -48,16 +44,11 @@ fn main() { // only for its `` variant. a::try_foo(other_variant_implements_mismatched_trait); //~^ ERROR E0277 - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `ImplementsTraitForUsize` only has // impls for the correct trait where the path is not misleading. a::try_foo(other_variant_implements_correct_trait); //~^ ERROR E0277 - //~| HELP the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree } } diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr index 9e5e110f8624e..27cad715b0738 100644 --- a/tests/ui/traits/bound/same-crate-name.stderr +++ b/tests/ui/traits/bound/same-crate-name.stderr @@ -1,23 +1,13 @@ -error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied +error[E0277]: the trait bound `Foo: crate_a1::Bar` is not satisfied --> $DIR/same-crate-name.rs:33:20 | LL | a::try_foo(foo); - | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo` + | ---------- ^^^ the trait `crate_a1::Bar` is not implemented for `Foo` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` + = note: `Foo` implements similarly named trait `crate_a2::Bar`, but not `crate_a1::Bar` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} @@ -28,26 +18,15 @@ note: required by a bound in `try_foo` LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` -error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:40:20 +error[E0277]: the trait bound `DoesNotImplementTrait: crate_a1::Bar` is not satisfied + --> $DIR/same-crate-name.rs:38:20 | LL | a::try_foo(implements_no_traits); - | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `crate_a1::Bar` is not implemented for `DoesNotImplementTrait` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the trait that was imported - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} @@ -58,26 +37,16 @@ note: required by a bound in `try_foo` LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` -error[E0277]: the trait bound `ImplementsWrongTraitConditionally: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:49:20 +error[E0277]: the trait bound `ImplementsWrongTraitConditionally: crate_a1::Bar` is not satisfied + --> $DIR/same-crate-name.rs:45:20 | LL | a::try_foo(other_variant_implements_mismatched_trait); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `crate_a1::Bar` is not implemented for `ImplementsWrongTraitConditionally` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` + = note: `ImplementsWrongTraitConditionally` implements similarly named trait `crate_a2::Bar`, but not `crate_a1::Bar` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} @@ -88,26 +57,15 @@ note: required by a bound in `try_foo` LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` -error[E0277]: the trait bound `ImplementsTraitForUsize: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:57:20 +error[E0277]: the trait bound `ImplementsTraitForUsize: crate_a1::Bar` is not satisfied + --> $DIR/same-crate-name.rs:51:20 | LL | a::try_foo(other_variant_implements_correct_trait); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `crate_a1::Bar` is not implemented for `ImplementsTraitForUsize` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the trait that was imported - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} diff --git a/tests/ui/traits/unhandled-crate-mod-issue-144888.rs b/tests/ui/traits/unhandled-crate-mod-issue-144888.rs index 8c9085ee80b35..41f233398d83b 100644 --- a/tests/ui/traits/unhandled-crate-mod-issue-144888.rs +++ b/tests/ui/traits/unhandled-crate-mod-issue-144888.rs @@ -18,6 +18,8 @@ where //~| ERROR the size for values of type `Self` cannot be known at compilation time //~| ERROR type mismatch resolving //~| ERROR the size for values of type `Self` cannot be known at compilation time + //~| ERROR type mismatch resolving + //~| ERROR the size for values of type `RustaceansAreAwesome` cannot be known at compilation time } trait Mirror { diff --git a/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr b/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr index 3208945a5b732..4cc5b41588efa 100644 --- a/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr +++ b/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr @@ -1,3 +1,19 @@ +error[E0271]: type mismatch resolving `::Assoc == ()` + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 + | +LL | fn transmute(&self) {} + | ^^^^^^^^^^^^^^^^^^^ expected `()`, found type parameter `T` + | + = note: expected unit type `()` + found type parameter `T` +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 + | +LL | impl> Mirror for T {} + | ---------- ^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + error[E0271]: type mismatch resolving `::Assoc == ()` --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | @@ -7,13 +23,27 @@ LL | fn transmute(&self) {} = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ | | | unsatisfied trait bound introduced here +error[E0277]: the size for values of type `RustaceansAreAwesome` cannot be known at compilation time + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 + | +LL | fn transmute(&self) {} + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 + | +LL | impl> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here + error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | @@ -21,7 +51,7 @@ LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -37,7 +67,7 @@ LL | trait Foo: Super = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -51,7 +81,7 @@ LL | trait Foo: Super | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -63,7 +93,7 @@ LL | trait Foo: Super + Sized | +++++++ error[E0046]: not all trait items implemented, missing: `Assoc` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:1 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:1 | LL | type Assoc; | ---------- `Assoc` from trait @@ -83,7 +113,7 @@ LL | fn transmute(&self) {} = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -97,7 +127,7 @@ LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -108,7 +138,7 @@ help: consider further restricting `Self` LL | fn transmute(&self) where Self: Sized {} | +++++++++++++++++ -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0046, E0271, E0277. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/transmutability/non_scalar_alignment_value.rs b/tests/ui/transmutability/non_scalar_alignment_value.rs index 24e97a2a55356..937fa39876303 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.rs +++ b/tests/ui/transmutability/non_scalar_alignment_value.rs @@ -1,4 +1,10 @@ -#![feature(gca_min_const_items, gca_macroless_args, transmutability)] +#![feature( + gca_adts, + gca_macroless_args, + gca_min_const_items, + min_adt_const_params, + transmutability +)] mod assert { use std::mem::{Assume, TransmuteFrom}; diff --git a/tests/ui/transmutability/non_scalar_alignment_value.stderr b/tests/ui/transmutability/non_scalar_alignment_value.stderr index 80a125d540a8f..020a557573bda 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.stderr +++ b/tests/ui/transmutability/non_scalar_alignment_value.stderr @@ -1,23 +1,23 @@ error: struct expression with missing field initialiser for `alignment` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `lifetimes` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `safety` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `validity` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs index df6d7aba8fd69..31fd47251660e 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.rs +++ b/tests/ui/type/type-mismatch-same-crate-name.rs @@ -16,17 +16,18 @@ fn main() { extern crate crate_a1 as a; a::try_foo(foo2); //~^ ERROR mismatched types - //~| NOTE expected `main::a::Foo`, found a different `main::a::Foo` + //~| NOTE expected `crate_a1::Foo`, found `crate_a2::Foo` //~| NOTE arguments to this function are incorrect - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| NOTE `crate_a2::Foo` and `crate_a1::Foo` have similar names, but are actually distinct types + //~| NOTE `crate_a2::Foo` is defined in crate `crate_a2` + //~| NOTE `crate_a1::Foo` is defined in crate `crate_a1` //~| NOTE function defined here - //~| HELP you can use `cargo tree` to explore your dependency tree a::try_bar(bar2); //~^ ERROR mismatched types - //~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar` + //~| NOTE expected trait `crate_a1::Bar`, found trait `crate_a2::Bar` //~| NOTE arguments to this function are incorrect - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| NOTE expected struct `Box<(dyn crate_a1::Bar + 'static)>` + //~| NOTE found struct `Box` //~| NOTE function defined here - //~| HELP you can use `cargo tree` to explore your dependency tree } } diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr index 2913b994e9529..71648741c2dd5 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.stderr +++ b/tests/ui/type/type-mismatch-same-crate-name.stderr @@ -2,21 +2,21 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:17:20 | LL | a::try_foo(foo2); - | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo` + | ---------- ^^^^ expected `crate_a1::Foo`, found `crate_a2::Foo` | | | arguments to this function are incorrect | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 + = note: `crate_a2::Foo` and `crate_a1::Foo` have similar names, but are actually distinct types +note: `crate_a2::Foo` is defined in crate `crate_a2` + --> $DIR/auxiliary/crate_a2.rs:1:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^ this is the expected type - | - ::: $DIR/auxiliary/crate_a2.rs:1:1 + | ^^^^^^^^^^^^^^ +note: `crate_a1::Foo` is defined in crate `crate_a1` + --> $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; - | -------------- this is the found type - = help: you can use `cargo tree` to explore your dependency tree + | ^^^^^^^^^^^^^^ note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | @@ -24,24 +24,15 @@ LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:24:20 + --> $DIR/type-mismatch-same-crate-name.rs:25:20 | LL | a::try_bar(bar2); - | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` + | ---------- ^^^^ expected trait `crate_a1::Bar`, found trait `crate_a2::Bar` | | | arguments to this function are incorrect | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:3:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree + = note: expected struct `Box<(dyn crate_a1::Bar + 'static)>` + found struct `Box` note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 | diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs index a155d9ade5cf3..9895ccbfd0926 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout index c2c79249a6bd4..f117acc810606 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout @@ -1,10 +1,9 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![expect(incomplete_features)] #![allow(dead_code)] -#![attr = Feature([gca_min_const_items#0, gca_macroless_args#0, -adt_const_params#0])] +#![attr = Feature([adt_const_params#0, gca_adts#0, gca_min_const_items#0, +gca_macroless_args#0])] extern crate std; #[attr = PreludeImport] use ::std::prelude::rust_2015::*;