From 152145546bc9ee1cbddd1837c3c010363771ec70 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Thu, 21 May 2026 22:15:03 +0200 Subject: [PATCH 01/16] Add share_trait feature gate --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + tests/ui/feature-gates/feature-gate-share-trait.rs | 5 +++++ 3 files changed, 8 insertions(+) create mode 100644 tests/ui/feature-gates/feature-gate-share-trait.rs diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8202f4c31c910..afb535112e11e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -711,6 +711,8 @@ declare_features! ( (unstable, s390x_target_feature, "1.82.0", Some(150259)), /// Allows the use of the `sanitize` attribute. (unstable, sanitize, "1.91.0", Some(39699)), + /// Allows use of the `Share` trait. + (unstable, share_trait, "CURRENT_RUSTC_VERSION", Some(156756)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), /// Target features on sparc. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 72339efd0a132..3182574049388 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1841,6 +1841,7 @@ symbols! { sha512_sm_x86, shadow_call_stack, shallow, + share_trait, shl, shl_assign, shorter_tail_lifetimes, diff --git a/tests/ui/feature-gates/feature-gate-share-trait.rs b/tests/ui/feature-gates/feature-gate-share-trait.rs new file mode 100644 index 0000000000000..664093948e6e0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-share-trait.rs @@ -0,0 +1,5 @@ +//@ check-pass + +#![feature(share_trait)] + +fn main() {} From e5a67968e609c49472990768ddbc9547880490bb Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Thu, 21 May 2026 22:25:59 +0200 Subject: [PATCH 02/16] Add unstable Share trait --- library/core/src/clone.rs | 24 +++++++++ library/core/src/prelude/v1.rs | 2 + tests/ui/README.md | 4 ++ .../ui/share-trait/share-trait-no-feature.rs | 20 +++++++ .../share-trait/share-trait-no-feature.stderr | 53 +++++++++++++++++++ .../share-trait/share-trait-not-in-prelude.rs | 9 ++++ .../share-trait-not-in-prelude.stderr | 14 +++++ .../share-trait/share-trait-requires-clone.rs | 10 ++++ .../share-trait-requires-clone.stderr | 17 ++++++ tests/ui/share-trait/share-trait.rs | 28 ++++++++++ 10 files changed, 181 insertions(+) create mode 100644 tests/ui/share-trait/share-trait-no-feature.rs create mode 100644 tests/ui/share-trait/share-trait-no-feature.stderr create mode 100644 tests/ui/share-trait/share-trait-not-in-prelude.rs create mode 100644 tests/ui/share-trait/share-trait-not-in-prelude.stderr create mode 100644 tests/ui/share-trait/share-trait-requires-clone.rs create mode 100644 tests/ui/share-trait/share-trait-requires-clone.stderr create mode 100644 tests/ui/share-trait/share-trait.rs diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index f2fa6fd0ca3e9..ab7e85a6aabaf 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -290,6 +290,30 @@ pub macro Clone($item:item) { /* compiler built-in */ } +/// A trait for types whose [`Clone`] operation creates another alias to the same value. +/// +/// `Share` marks types where cloning preserves the identity of the underlying value instead of +/// creating an independent owned copy. The distinction is semantic, not cost-based: implementing +/// `Share` does not merely mean that cloning is cheap, constant-time, allocation-free, or +/// harmless. +/// +/// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone) for +/// implementors. +// FIXME(share_trait): The public location of `Share` is still unresolved; if libs-api confirms a +// different home, move this trait and update tests. +#[unstable(feature = "share_trait", issue = "156756")] +pub trait Share: Clone { + /// Creates another alias to the same underlying value. + /// + /// This is equivalent to calling [`Clone::clone`]. + #[unstable(feature = "share_trait", issue = "156756")] + // FIXME(share_trait): The default method body form is unresolved; keep the explicit + // `Clone::clone(self)` spelling until the tracking issue decides it. + fn share(&self) -> Self { + Clone::clone(self) + } +} + /// Trait for objects whose [`Clone`] impl is lightweight (e.g. reference-counted) /// /// Cloning an object implementing this trait should in general: diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 6122ab12ec351..d763640bc9307 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -30,6 +30,8 @@ pub use crate::mem::{align_of, align_of_val, size_of, size_of_val}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::clone::Clone; +// FIXME(share_trait): Whether `Share` belongs in the prelude is unresolved; do not re-export it +// here until that API question is decided. #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::cmp::{Eq, Ord, PartialEq, PartialOrd}; diff --git a/tests/ui/README.md b/tests/ui/README.md index 39402f78bb5ec..386e77ae2bd3d 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1244,6 +1244,10 @@ In this directory, multiple crates are compiled, but some of them have `inline` Tests on name shadowing. +## `tests/ui/share-trait` + +Tests for the unstable `Share` trait. + ## `tests/ui/shell-argfiles/`: `-Z shell-argfiles` command line flag The `-Zshell-argfiles` compiler flag allows argfiles to be parsed using POSIX "shell-style" quoting. When enabled, the compiler will use shlex to parse the arguments from argfiles specified with `@shell:`. diff --git a/tests/ui/share-trait/share-trait-no-feature.rs b/tests/ui/share-trait/share-trait-no-feature.rs new file mode 100644 index 0000000000000..2b4791d2eb034 --- /dev/null +++ b/tests/ui/share-trait/share-trait-no-feature.rs @@ -0,0 +1,20 @@ +use std::clone::Share; +//~^ ERROR use of unstable library feature `share_trait` + +#[derive(Clone)] +struct Alias; + +impl Share for Alias {} +//~^ ERROR use of unstable library feature `share_trait` + +fn share_generic(value: &T) -> T { + //~^ ERROR use of unstable library feature `share_trait` + value.share() + //~^ ERROR use of unstable library feature `share_trait` +} + +fn main() { + let value = Alias; + let _ = Share::share(&value); + //~^ ERROR use of unstable library feature `share_trait` +} diff --git a/tests/ui/share-trait/share-trait-no-feature.stderr b/tests/ui/share-trait/share-trait-no-feature.stderr new file mode 100644 index 0000000000000..344f5d8670f63 --- /dev/null +++ b/tests/ui/share-trait/share-trait-no-feature.stderr @@ -0,0 +1,53 @@ +error[E0658]: use of unstable library feature `share_trait` + --> $DIR/share-trait-no-feature.rs:1:5 + | +LL | use std::clone::Share; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` 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 `share_trait` + --> $DIR/share-trait-no-feature.rs:7:6 + | +LL | impl Share for Alias {} + | ^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` 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 `share_trait` + --> $DIR/share-trait-no-feature.rs:10:21 + | +LL | fn share_generic(value: &T) -> T { + | ^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` 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 `share_trait` + --> $DIR/share-trait-no-feature.rs:18:13 + | +LL | let _ = Share::share(&value); + | ^^^^^^^^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` 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 `share_trait` + --> $DIR/share-trait-no-feature.rs:12:11 + | +LL | value.share() + | ^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` 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: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/share-trait/share-trait-not-in-prelude.rs b/tests/ui/share-trait/share-trait-not-in-prelude.rs new file mode 100644 index 0000000000000..4876fac2b8c1d --- /dev/null +++ b/tests/ui/share-trait/share-trait-not-in-prelude.rs @@ -0,0 +1,9 @@ +#![feature(share_trait)] + +#[derive(Clone)] +struct Alias; + +impl Share for Alias {} +//~^ ERROR cannot find trait `Share` in this scope + +fn main() {} diff --git a/tests/ui/share-trait/share-trait-not-in-prelude.stderr b/tests/ui/share-trait/share-trait-not-in-prelude.stderr new file mode 100644 index 0000000000000..733c8f2d2b215 --- /dev/null +++ b/tests/ui/share-trait/share-trait-not-in-prelude.stderr @@ -0,0 +1,14 @@ +error[E0405]: cannot find trait `Share` in this scope + --> $DIR/share-trait-not-in-prelude.rs:6:6 + | +LL | impl Share for Alias {} + | ^^^^^ not found in this scope + | +help: consider importing this trait + | +LL + use std::clone::Share; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/share-trait/share-trait-requires-clone.rs b/tests/ui/share-trait/share-trait-requires-clone.rs new file mode 100644 index 0000000000000..a70ae3ade37d0 --- /dev/null +++ b/tests/ui/share-trait/share-trait-requires-clone.rs @@ -0,0 +1,10 @@ +#![feature(share_trait)] + +use std::clone::Share; + +struct NotClone; + +impl Share for NotClone {} +//~^ ERROR the trait bound `NotClone: Clone` is not satisfied + +fn main() {} diff --git a/tests/ui/share-trait/share-trait-requires-clone.stderr b/tests/ui/share-trait/share-trait-requires-clone.stderr new file mode 100644 index 0000000000000..ac775db690a40 --- /dev/null +++ b/tests/ui/share-trait/share-trait-requires-clone.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/share-trait-requires-clone.rs:7:16 + | +LL | impl Share for NotClone {} + | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` + | +note: required by a bound in `Share` + --> $SRC_DIR/core/src/clone.rs:LL:COL +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct NotClone; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/share-trait/share-trait.rs b/tests/ui/share-trait/share-trait.rs new file mode 100644 index 0000000000000..4292222d97512 --- /dev/null +++ b/tests/ui/share-trait/share-trait.rs @@ -0,0 +1,28 @@ +//@ check-pass + +#![feature(share_trait)] + +use std::clone::Share; + +#[derive(Debug, PartialEq)] +struct Alias(u8); + +impl Clone for Alias { + fn clone(&self) -> Self { + Alias(self.0 + 1) + } +} + +impl Share for Alias {} + +fn share_generic(value: &T) -> T { + value.share() +} + +fn main() { + let value = Alias(1); + + assert_eq!(Share::share(&value), Alias(2)); + assert_eq!(value.share(), Alias(2)); + assert_eq!(share_generic(&value), Alias(2)); +} From 02109ee82217c3417f5ca9ee16322eea3fb9d5a6 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Thu, 21 May 2026 22:34:04 +0200 Subject: [PATCH 03/16] Implement Share for shared references --- library/core/src/clone.rs | 7 ++- .../share-trait-non-implementors.rs | 19 ++++++ .../share-trait-non-implementors.stderr | 60 +++++++++++++++++++ tests/ui/share-trait/share-trait.rs | 12 ++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 tests/ui/share-trait/share-trait-non-implementors.rs create mode 100644 tests/ui/share-trait/share-trait-non-implementors.stderr diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index ab7e85a6aabaf..1cc68def00cb9 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -625,7 +625,7 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr { /// are implemented in `traits::SelectionContext::copy_clone_conditions()` /// in `rustc_trait_selection`. mod impls { - use super::TrivialClone; + use super::{Share, TrivialClone}; use crate::marker::PointeeSized; macro_rules! impl_clone { @@ -713,6 +713,11 @@ mod impls { #[rustc_const_unstable(feature = "const_clone", issue = "142757")] unsafe impl const TrivialClone for &T {} + #[unstable(feature = "share_trait", issue = "156756")] + impl Share for &T {} + + // FIXME(share_trait): Whether mutable references are non-candidates is unresolved; keep + // `Share` unimplemented for `&mut T` until that API question is decided. /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl !Clone for &mut T {} diff --git a/tests/ui/share-trait/share-trait-non-implementors.rs b/tests/ui/share-trait/share-trait-non-implementors.rs new file mode 100644 index 0000000000000..a53f10fb9e6b3 --- /dev/null +++ b/tests/ui/share-trait/share-trait-non-implementors.rs @@ -0,0 +1,19 @@ +#![feature(share_trait)] + +use std::clone::Share; + +fn require_share() {} + +fn main() { + require_share::<&mut i32>(); + //~^ ERROR the trait bound `&mut i32: Share` is not satisfied + + require_share::(); + //~^ ERROR the trait bound `String: Share` is not satisfied + + require_share::>(); + //~^ ERROR the trait bound `Vec: Share` is not satisfied + + require_share::>(); + //~^ ERROR the trait bound `Box: Share` is not satisfied +} diff --git a/tests/ui/share-trait/share-trait-non-implementors.stderr b/tests/ui/share-trait/share-trait-non-implementors.stderr new file mode 100644 index 0000000000000..88655d64595db --- /dev/null +++ b/tests/ui/share-trait/share-trait-non-implementors.stderr @@ -0,0 +1,60 @@ +error[E0277]: the trait bound `&mut i32: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:8:21 + | +LL | require_share::<&mut i32>(); + | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `&mut i32` + | +help: the trait `Share` is implemented for `&T` + --> $SRC_DIR/core/src/clone.rs:LL:COL + = note: `Share` is implemented for `&i32`, but not for `&mut i32` +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error[E0277]: the trait bound `String: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:11:21 + | +LL | require_share::(); + | ^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `String` + | +help: the trait `Share` is implemented for `&T` + --> $SRC_DIR/core/src/clone.rs:LL:COL +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error[E0277]: the trait bound `Vec: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:14:21 + | +LL | require_share::>(); + | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `Vec` + | +help: the trait `Share` is implemented for `&T` + --> $SRC_DIR/core/src/clone.rs:LL:COL +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error[E0277]: the trait bound `Box: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:17:21 + | +LL | require_share::>(); + | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `Box` + | +help: the trait `Share` is implemented for `&T` + --> $SRC_DIR/core/src/clone.rs:LL:COL +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/share-trait/share-trait.rs b/tests/ui/share-trait/share-trait.rs index 4292222d97512..d909139116e00 100644 --- a/tests/ui/share-trait/share-trait.rs +++ b/tests/ui/share-trait/share-trait.rs @@ -25,4 +25,16 @@ fn main() { assert_eq!(Share::share(&value), Alias(2)); assert_eq!(value.share(), Alias(2)); assert_eq!(share_generic(&value), Alias(2)); + + let number = 3; + let shared = &number; + let shared_again = shared.share(); + let shared_fqs: &i32 = Share::share(&shared); + let shared_generic: &i32 = share_generic(&shared); + assert!(std::ptr::eq(shared, shared_again)); + assert!(std::ptr::eq(shared_fqs, shared)); + assert!(std::ptr::eq(shared_generic, shared)); + + let text: &str = "text"; + assert!(std::ptr::eq(text, text.share())); } From d082ac96d50bfdbf7017c251f00b10137bd3a2db Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Thu, 21 May 2026 23:50:46 +0200 Subject: [PATCH 04/16] Tighten initial Share trait implementation --- tests/ui/share-trait/share-trait.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/ui/share-trait/share-trait.rs b/tests/ui/share-trait/share-trait.rs index d909139116e00..7a099cd96cb85 100644 --- a/tests/ui/share-trait/share-trait.rs +++ b/tests/ui/share-trait/share-trait.rs @@ -2,7 +2,9 @@ #![feature(share_trait)] -use std::clone::Share; +extern crate core; + +use core::clone::Share; #[derive(Debug, PartialEq)] struct Alias(u8); @@ -23,6 +25,7 @@ fn main() { let value = Alias(1); assert_eq!(Share::share(&value), Alias(2)); + assert_eq!(std::clone::Share::share(&value), Alias(2)); assert_eq!(value.share(), Alias(2)); assert_eq!(share_generic(&value), Alias(2)); @@ -31,10 +34,11 @@ fn main() { let shared_again = shared.share(); let shared_fqs: &i32 = Share::share(&shared); let shared_generic: &i32 = share_generic(&shared); + assert!(std::ptr::eq(shared, shared_again)); assert!(std::ptr::eq(shared_fqs, shared)); assert!(std::ptr::eq(shared_generic, shared)); - let text: &str = "text"; - assert!(std::ptr::eq(text, text.share())); + let slice: &[i32] = &[1, 2, 3]; + assert!(std::ptr::eq(slice, slice.share())); } From fc33b6d4f46d477c608d3488e14c8ff60ccceb71 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 00:09:24 +0200 Subject: [PATCH 05/16] Add Share impl for Rc --- library/alloc/src/lib.rs | 1 + library/alloc/src/rc.rs | 8 ++++++- tests/ui/share-trait/share-trait-rc.rs | 32 ++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/ui/share-trait/share-trait-rc.rs diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7b41023ff31bf..5fe5464ab2cdd 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -144,6 +144,7 @@ #![feature(ptr_metadata)] #![feature(rev_into_inner)] #![feature(set_ptr_value)] +#![feature(share_trait)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] #![feature(slice_index_methods)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 2905170d22a76..67fa09d22f77f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -245,7 +245,7 @@ use core::any::Any; use core::cell::{Cell, CloneFromCell}; #[cfg(not(no_global_oom_handling))] use core::clone::TrivialClone; -use core::clone::{CloneToUninit, UseCloned}; +use core::clone::{CloneToUninit, Share, UseCloned}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; @@ -2525,6 +2525,12 @@ impl Clone for Rc { #[unstable(feature = "ergonomic_clones", issue = "132290")] impl UseCloned for Rc {} +// FIXME(share_trait): The initial `Share` impl set is still being confirmed in +// rust-lang/rust#156756. This assumes cloning `Rc` creates a clone-as-alias +// value because the new handle points to the same allocation. +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Rc {} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Rc { diff --git a/tests/ui/share-trait/share-trait-rc.rs b/tests/ui/share-trait/share-trait-rc.rs new file mode 100644 index 0000000000000..7de6936bcc9cb --- /dev/null +++ b/tests/ui/share-trait/share-trait-rc.rs @@ -0,0 +1,32 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::cell::Cell; +use std::clone::Share; +use std::rc::Rc; + +trait Value { + fn get(&self) -> i32; +} + +impl Value for Cell { + fn get(&self) -> i32 { + Cell::get(self) + } +} + +fn main() { + let value = Rc::new(Cell::new(1)); + let shared = value.share(); + + assert!(Rc::ptr_eq(&value, &shared)); + shared.set(2); + assert_eq!(value.get(), 2); + + let dyn_value: Rc = Rc::new(Cell::new(3)); + let shared_dyn_value = dyn_value.share(); + + assert!(Rc::ptr_eq(&dyn_value, &shared_dyn_value)); + assert_eq!(shared_dyn_value.get(), 3); +} From 78b0f9db850bdcfb3528df66eb51a2872d60e077 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 00:11:38 +0200 Subject: [PATCH 06/16] Add Share impl for Arc --- library/alloc/src/sync.rs | 8 ++++++- tests/ui/share-trait/share-trait-arc.rs | 31 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/ui/share-trait/share-trait-arc.rs diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 229fcd2b429cf..75ee1787e557b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -12,7 +12,7 @@ use core::any::Any; use core::cell::CloneFromCell; #[cfg(not(no_global_oom_handling))] use core::clone::TrivialClone; -use core::clone::{CloneToUninit, UseCloned}; +use core::clone::{CloneToUninit, Share, UseCloned}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; @@ -2436,6 +2436,12 @@ impl Clone for Arc { #[unstable(feature = "ergonomic_clones", issue = "132290")] impl UseCloned for Arc {} +// FIXME(share_trait): The initial `Share` impl set is still being confirmed in +// rust-lang/rust#156756. This assumes cloning `Arc` creates a clone-as-alias +// value because the new handle points to the same allocation. +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Arc {} + #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Arc { type Target = T; diff --git a/tests/ui/share-trait/share-trait-arc.rs b/tests/ui/share-trait/share-trait-arc.rs new file mode 100644 index 0000000000000..1a4f421caeeb9 --- /dev/null +++ b/tests/ui/share-trait/share-trait-arc.rs @@ -0,0 +1,31 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::clone::Share; +use std::sync::{Arc, Mutex}; + +trait Value { + fn get(&self) -> i32; +} + +impl Value for Mutex { + fn get(&self) -> i32 { + *self.lock().unwrap() + } +} + +fn main() { + let value = Arc::new(Mutex::new(1)); + let shared = value.share(); + + assert!(Arc::ptr_eq(&value, &shared)); + *shared.lock().unwrap() = 2; + assert_eq!(*value.lock().unwrap(), 2); + + let dyn_value: Arc = Arc::new(Mutex::new(3)); + let shared_dyn_value = dyn_value.share(); + + assert!(Arc::ptr_eq(&dyn_value, &shared_dyn_value)); + assert_eq!(shared_dyn_value.get(), 3); +} From 4b32cb2b005ade0d20114e3289a50266d7040cfa Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 00:14:24 +0200 Subject: [PATCH 07/16] Add Share impl for mpsc Sender --- library/std/src/lib.rs | 1 + library/std/src/sync/mpsc.rs | 8 ++++++++ .../ui/share-trait/share-trait-mpsc-sender.rs | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/ui/share-trait/share-trait-mpsc-sender.rs diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8b863b07ce5d9..cb0f8edb7b852 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -369,6 +369,7 @@ #![feature(random)] #![feature(raw_os_error_ty)] #![feature(seek_io_take_position)] +#![feature(share_trait)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index 8c40f07f0d17d..c2a3ee47fe100 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -142,6 +142,8 @@ // not exposed publicly, but if you are curious about the implementation, // that's where everything is. +use core::clone::Share; + use crate::sync::mpmc; use crate::time::{Duration, Instant}; use crate::{error, fmt}; @@ -645,6 +647,12 @@ impl Clone for Sender { } } +// FIXME(share_trait): The sender-like `Share` impl set is still being confirmed in +// rust-lang/rust#156756. This assumes cloning `Sender` creates a clone-as-alias +// value because both handles send to the same receiving endpoint. +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Sender {} + #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for Sender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/tests/ui/share-trait/share-trait-mpsc-sender.rs b/tests/ui/share-trait/share-trait-mpsc-sender.rs new file mode 100644 index 0000000000000..1939b10fbf43a --- /dev/null +++ b/tests/ui/share-trait/share-trait-mpsc-sender.rs @@ -0,0 +1,19 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::clone::Share; +use std::sync::mpsc::channel; + +fn main() { + let (sender, receiver) = channel(); + let shared_sender = sender.share(); + + sender.send(1).unwrap(); + shared_sender.send(2).unwrap(); + + let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()]; + received.sort(); + + assert_eq!(received, [1, 2]); +} From 4a32c28276a5ebefbe48efdf4deb57eb5e3d50e3 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 00:16:29 +0200 Subject: [PATCH 08/16] Add Share impl for mpsc SyncSender --- library/std/src/sync/mpsc.rs | 6 ++++++ .../share-trait-mpsc-sync-sender.rs | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/share-trait/share-trait-mpsc-sync-sender.rs diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index c2a3ee47fe100..95cea6df880d5 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -782,6 +782,12 @@ impl Clone for SyncSender { } } +// FIXME(share_trait): The sender-like `Share` impl set is still being confirmed in +// rust-lang/rust#156756. This assumes cloning `SyncSender` creates a clone-as-alias +// value because both handles send to the same receiving endpoint. +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for SyncSender {} + #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for SyncSender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/tests/ui/share-trait/share-trait-mpsc-sync-sender.rs b/tests/ui/share-trait/share-trait-mpsc-sync-sender.rs new file mode 100644 index 0000000000000..6b10d05324283 --- /dev/null +++ b/tests/ui/share-trait/share-trait-mpsc-sync-sender.rs @@ -0,0 +1,19 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::clone::Share; +use std::sync::mpsc::sync_channel; + +fn main() { + let (sender, receiver) = sync_channel(2); + let shared_sender = sender.share(); + + sender.send(1).unwrap(); + shared_sender.send(2).unwrap(); + + let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()]; + received.sort(); + + assert_eq!(received, [1, 2]); +} From 71bcc49e5ffcd34b9bc7e8410bd5ffcf4d27607c Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 00:19:26 +0200 Subject: [PATCH 09/16] Update Share non-implementor diagnostics --- .../share-trait-non-implementors.stderr | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/ui/share-trait/share-trait-non-implementors.stderr b/tests/ui/share-trait/share-trait-non-implementors.stderr index 88655d64595db..8056e34beea55 100644 --- a/tests/ui/share-trait/share-trait-non-implementors.stderr +++ b/tests/ui/share-trait/share-trait-non-implementors.stderr @@ -4,8 +4,12 @@ error[E0277]: the trait bound `&mut i32: Share` is not satisfied LL | require_share::<&mut i32>(); | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `&mut i32` | -help: the trait `Share` is implemented for `&T` - --> $SRC_DIR/core/src/clone.rs:LL:COL + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender = note: `Share` is implemented for `&i32`, but not for `&mut i32` note: required by a bound in `require_share` --> $DIR/share-trait-non-implementors.rs:5:21 @@ -19,8 +23,12 @@ error[E0277]: the trait bound `String: Share` is not satisfied LL | require_share::(); | ^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `String` | -help: the trait `Share` is implemented for `&T` - --> $SRC_DIR/core/src/clone.rs:LL:COL + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender note: required by a bound in `require_share` --> $DIR/share-trait-non-implementors.rs:5:21 | @@ -33,8 +41,12 @@ error[E0277]: the trait bound `Vec: Share` is not satisfied LL | require_share::>(); | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `Vec` | -help: the trait `Share` is implemented for `&T` - --> $SRC_DIR/core/src/clone.rs:LL:COL + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender note: required by a bound in `require_share` --> $DIR/share-trait-non-implementors.rs:5:21 | @@ -47,8 +59,12 @@ error[E0277]: the trait bound `Box: Share` is not satisfied LL | require_share::>(); | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `Box` | -help: the trait `Share` is implemented for `&T` - --> $SRC_DIR/core/src/clone.rs:LL:COL + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender note: required by a bound in `require_share` --> $DIR/share-trait-non-implementors.rs:5:21 | From 9b3cd578ab676ccab38ef22821a31b687a9245e3 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 07:13:06 +0200 Subject: [PATCH 10/16] Remove provisional Share trait FIXME notes --- library/alloc/src/rc.rs | 3 --- library/alloc/src/sync.rs | 3 --- library/core/src/clone.rs | 6 ------ library/core/src/prelude/v1.rs | 2 -- library/std/src/sync/mpsc.rs | 6 ------ 5 files changed, 20 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 67fa09d22f77f..8150767339e18 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2525,9 +2525,6 @@ impl Clone for Rc { #[unstable(feature = "ergonomic_clones", issue = "132290")] impl UseCloned for Rc {} -// FIXME(share_trait): The initial `Share` impl set is still being confirmed in -// rust-lang/rust#156756. This assumes cloning `Rc` creates a clone-as-alias -// value because the new handle points to the same allocation. #[unstable(feature = "share_trait", issue = "156756")] impl Share for Rc {} diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 75ee1787e557b..17476a4e2b1e7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2436,9 +2436,6 @@ impl Clone for Arc { #[unstable(feature = "ergonomic_clones", issue = "132290")] impl UseCloned for Arc {} -// FIXME(share_trait): The initial `Share` impl set is still being confirmed in -// rust-lang/rust#156756. This assumes cloning `Arc` creates a clone-as-alias -// value because the new handle points to the same allocation. #[unstable(feature = "share_trait", issue = "156756")] impl Share for Arc {} diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 1cc68def00cb9..84d0ab6413ad3 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -299,16 +299,12 @@ pub macro Clone($item:item) { /// /// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone) for /// implementors. -// FIXME(share_trait): The public location of `Share` is still unresolved; if libs-api confirms a -// different home, move this trait and update tests. #[unstable(feature = "share_trait", issue = "156756")] pub trait Share: Clone { /// Creates another alias to the same underlying value. /// /// This is equivalent to calling [`Clone::clone`]. #[unstable(feature = "share_trait", issue = "156756")] - // FIXME(share_trait): The default method body form is unresolved; keep the explicit - // `Clone::clone(self)` spelling until the tracking issue decides it. fn share(&self) -> Self { Clone::clone(self) } @@ -716,8 +712,6 @@ mod impls { #[unstable(feature = "share_trait", issue = "156756")] impl Share for &T {} - // FIXME(share_trait): Whether mutable references are non-candidates is unresolved; keep - // `Share` unimplemented for `&mut T` until that API question is decided. /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl !Clone for &mut T {} diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index d763640bc9307..6122ab12ec351 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -30,8 +30,6 @@ pub use crate::mem::{align_of, align_of_val, size_of, size_of_val}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::clone::Clone; -// FIXME(share_trait): Whether `Share` belongs in the prelude is unresolved; do not re-export it -// here until that API question is decided. #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::cmp::{Eq, Ord, PartialEq, PartialOrd}; diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index 95cea6df880d5..b74f84ff465c0 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -647,9 +647,6 @@ impl Clone for Sender { } } -// FIXME(share_trait): The sender-like `Share` impl set is still being confirmed in -// rust-lang/rust#156756. This assumes cloning `Sender` creates a clone-as-alias -// value because both handles send to the same receiving endpoint. #[unstable(feature = "share_trait", issue = "156756")] impl Share for Sender {} @@ -782,9 +779,6 @@ impl Clone for SyncSender { } } -// FIXME(share_trait): The sender-like `Share` impl set is still being confirmed in -// rust-lang/rust#156756. This assumes cloning `SyncSender` creates a clone-as-alias -// value because both handles send to the same receiving endpoint. #[unstable(feature = "share_trait", issue = "156756")] impl Share for SyncSender {} From c01e32073c1fe9e93c03d56f7cd635eb21ea9219 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 07:21:45 +0200 Subject: [PATCH 11/16] Document unstable Share trait semantics --- library/core/src/clone.rs | 72 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 84d0ab6413ad3..6c2b4fa151b86 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -292,13 +292,75 @@ pub macro Clone($item:item) { /// A trait for types whose [`Clone`] operation creates another alias to the same value. /// -/// `Share` marks types where cloning preserves the identity of the underlying value instead of -/// creating an independent owned copy. The distinction is semantic, not cost-based: implementing -/// `Share` does not merely mean that cloning is cheap, constant-time, allocation-free, or -/// harmless. +/// `Share` marks types where cloning creates another handle or reference to the same logical +/// resource or shared state, rather than an independent owned value. The distinction is semantic, +/// not cost-based: implementing `Share` does not merely mean that cloning is cheap, constant-time, +/// allocation-free, or convenient. /// /// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone) for -/// implementors. +/// implementors, but communicates that the resulting value aliases the same underlying resource. +/// +/// Shared references, [`Rc`](std::rc::Rc), [`Arc`](std::sync::Arc), +/// [`Sender`](std::sync::mpsc::Sender), and [`SyncSender`](std::sync::mpsc::SyncSender) are +/// examples of types that can be shared this way. Types such as [`Vec`](std::vec::Vec), +/// [`String`](std::string::String), and [`Box`](std::boxed::Box) are not `Share` even though they +/// implement `Clone`, because cloning them creates another owned value rather than another handle +/// to the same logical resource. +/// +/// # Examples +/// +/// ``` +/// #![feature(share_trait)] +/// +/// use std::cell::Cell; +/// use std::clone::Share; +/// use std::rc::Rc; +/// use std::sync::{ +/// Arc, +/// atomic::{AtomicUsize, Ordering}, +/// }; +/// +/// let value = 1; +/// let reference = &value; +/// assert!(std::ptr::eq(reference, reference.share())); +/// +/// let rc = Rc::new(Cell::new(2)); +/// let shared_rc = rc.share(); +/// assert!(Rc::ptr_eq(&rc, &shared_rc)); +/// shared_rc.set(3); +/// assert_eq!(rc.get(), 3); +/// +/// let arc = Arc::new(AtomicUsize::new(4)); +/// let shared_arc = arc.share(); +/// assert!(Arc::ptr_eq(&arc, &shared_arc)); +/// shared_arc.store(5, Ordering::Relaxed); +/// assert_eq!(arc.load(Ordering::Relaxed), 5); +/// ``` +/// +/// ``` +/// #![feature(share_trait)] +/// +/// use std::clone::Share; +/// use std::sync::mpsc::{channel, sync_channel}; +/// +/// let (sender, receiver) = channel(); +/// let shared_sender = sender.share(); +/// sender.send(1).unwrap(); +/// shared_sender.send(2).unwrap(); +/// +/// let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()]; +/// received.sort(); +/// assert_eq!(received, [1, 2]); +/// +/// let (sync_sender, sync_receiver) = sync_channel(2); +/// let shared_sync_sender = sync_sender.share(); +/// sync_sender.send(3).unwrap(); +/// shared_sync_sender.send(4).unwrap(); +/// +/// let mut received = [sync_receiver.recv().unwrap(), sync_receiver.recv().unwrap()]; +/// received.sort(); +/// assert_eq!(received, [3, 4]); +/// ``` #[unstable(feature = "share_trait", issue = "156756")] pub trait Share: Clone { /// Creates another alias to the same underlying value. From 3a6cb0519d5c6595f6815992142d66964612b8ac Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Fri, 22 May 2026 09:15:36 -0400 Subject: [PATCH 12/16] Add `#[doc(alias = "phi")]` for float GOLDEN_RATIO constants --- library/core/src/num/f128.rs | 1 + library/core/src/num/f16.rs | 1 + library/core/src/num/f32.rs | 1 + library/core/src/num/f64.rs | 1 + 4 files changed, 4 insertions(+) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index d381402b469f4..cd1987aa959dd 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -33,6 +33,7 @@ pub mod consts { pub const TAU: f128 = 6.28318530717958647692528676655900576839433879875021164194989_f128; /// The golden ratio (φ) + #[doc(alias = "phi")] #[unstable(feature = "f128", issue = "116909")] pub const GOLDEN_RATIO: f128 = 1.61803398874989484820458683436563811772030917980576286213545_f128; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index c26ae17d870cc..ef8eb3c0b57a0 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -35,6 +35,7 @@ pub mod consts { pub const TAU: f16 = 6.28318530717958647692528676655900577_f16; /// The golden ratio (φ) + #[doc(alias = "phi")] #[unstable(feature = "f16", issue = "116909")] pub const GOLDEN_RATIO: f16 = 1.618033988749894848204586834365638118_f16; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 24c97a6491c11..2a7506f198589 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -292,6 +292,7 @@ pub mod consts { pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; /// The golden ratio (φ) + #[doc(alias = "phi")] #[stable(feature = "euler_gamma_golden_ratio", since = "1.94.0")] pub const GOLDEN_RATIO: f32 = 1.618033988749894848204586834365638118_f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index be045033a3553..8b77a3b7b0bde 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -292,6 +292,7 @@ pub mod consts { pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; /// The golden ratio (φ) + #[doc(alias = "phi")] #[stable(feature = "euler_gamma_golden_ratio", since = "1.94.0")] pub const GOLDEN_RATIO: f64 = 1.618033988749894848204586834365638118_f64; From 501ab4e8c59d865b428b63498577a08ab4bf3cf0 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Fri, 22 May 2026 16:21:32 +0200 Subject: [PATCH 13/16] Clarify Share trait docs --- library/core/src/clone.rs | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 6c2b4fa151b86..0c3e90b78103a 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -290,21 +290,23 @@ pub macro Clone($item:item) { /* compiler built-in */ } -/// A trait for types whose [`Clone`] operation creates another alias to the same value. -/// -/// `Share` marks types where cloning creates another handle or reference to the same logical -/// resource or shared state, rather than an independent owned value. The distinction is semantic, -/// not cost-based: implementing `Share` does not merely mean that cloning is cheap, constant-time, -/// allocation-free, or convenient. -/// -/// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone) for -/// implementors, but communicates that the resulting value aliases the same underlying resource. -/// -/// Shared references, [`Rc`](std::rc::Rc), [`Arc`](std::sync::Arc), -/// [`Sender`](std::sync::mpsc::Sender), and [`SyncSender`](std::sync::mpsc::SyncSender) are -/// examples of types that can be shared this way. Types such as [`Vec`](std::vec::Vec), -/// [`String`](std::string::String), and [`Box`](std::boxed::Box) are not `Share` even though they -/// implement `Clone`, because cloning them creates another owned value rather than another handle +/// A trait for types whose [`Clone`] operation creates another alias to the same +/// logical resource or shared state. +/// +/// `Share` marks types where cloning creates another handle, reference, or alias +/// to the same logical resource or shared state, rather than an independent owned +/// value. The distinction is semantic, not cost-based: implementing `Share` does +/// not merely mean that cloning is cheap, constant-time, allocation-free, or +/// convenient. +/// +/// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone) +/// for implementors, but communicates that the resulting value aliases the same +/// underlying resource. +/// +/// Shared references, `Rc`, `Arc`, `Sender`, and `SyncSender` are +/// examples of types that can be shared this way. Types such as `Vec`, +/// `String`, and `Box` are not `Share` even though they implement `Clone`, +/// because cloning them creates another owned value rather than another handle /// to the same logical resource. /// /// # Examples @@ -363,7 +365,7 @@ pub macro Clone($item:item) { /// ``` #[unstable(feature = "share_trait", issue = "156756")] pub trait Share: Clone { - /// Creates another alias to the same underlying value. + /// Creates another alias to the same underlying resource or shared state. /// /// This is equivalent to calling [`Clone::clone`]. #[unstable(feature = "share_trait", issue = "156756")] From 2f953da599463b6dda06d4948fc23bc301e0a6ce Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Sat, 23 May 2026 17:33:22 +0200 Subject: [PATCH 14/16] Remove unnecessary Share feature gate plumbing --- compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_span/src/symbol.rs | 1 - tests/ui/feature-gates/feature-gate-share-trait.rs | 5 ----- 3 files changed, 8 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-share-trait.rs diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index afb535112e11e..8202f4c31c910 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -711,8 +711,6 @@ declare_features! ( (unstable, s390x_target_feature, "1.82.0", Some(150259)), /// Allows the use of the `sanitize` attribute. (unstable, sanitize, "1.91.0", Some(39699)), - /// Allows use of the `Share` trait. - (unstable, share_trait, "CURRENT_RUSTC_VERSION", Some(156756)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), /// Target features on sparc. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3182574049388..72339efd0a132 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1841,7 +1841,6 @@ symbols! { sha512_sm_x86, shadow_call_stack, shallow, - share_trait, shl, shl_assign, shorter_tail_lifetimes, diff --git a/tests/ui/feature-gates/feature-gate-share-trait.rs b/tests/ui/feature-gates/feature-gate-share-trait.rs deleted file mode 100644 index 664093948e6e0..0000000000000 --- a/tests/ui/feature-gates/feature-gate-share-trait.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ check-pass - -#![feature(share_trait)] - -fn main() {} From 0c7388c750d537b7670d58c1ab480829b7960d39 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 May 2026 04:03:55 +0200 Subject: [PATCH 15/16] Fix jump to def link generation on primitive type associated methods --- src/librustdoc/clean/types.rs | 36 ++++++++++++++++++- src/librustdoc/html/format.rs | 35 ++++++++++-------- tests/rustdoc-html/jump-to-def/prim-method.rs | 16 +++++++++ 3 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 tests/rustdoc-html/jump-to-def/prim-method.rs diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2fe0c8d8776dd..2f992c622c496 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -20,7 +20,7 @@ use rustc_index::IndexVec; use rustc_metadata::rendered_const; use rustc_middle::span_bug; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::{self, TyCtxt, Visibility}; +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, }; @@ -1758,6 +1758,40 @@ impl PrimitiveType { } } + pub(crate) fn from_ty(ty: Ty<'_>) -> Option { + match ty.kind() { + ty::Array(..) => Some(Self::Array), + ty::Bool => Some(Self::Bool), + ty::Char => Some(Self::Char), + ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn), + ty::Int(int) => Some(Self::from(*int)), + ty::Uint(uint) => Some(Self::from(*uint)), + ty::Float(float) => Some(Self::from(*float)), + ty::Never => Some(Self::Never), + ty::Pat(..) => Some(Self::Pat), + ty::RawPtr(..) => Some(Self::RawPointer), + ty::Ref(..) => Some(Self::Reference), + ty::Slice(..) => Some(Self::Slice), + ty::Str => Some(Self::Str), + ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit), + ty::Tuple(_) => Some(Self::Tuple), + ty::Adt(..) + | ty::Alias(..) + | ty::Bound(..) + | ty::Closure(..) + | ty::Coroutine(..) + | ty::CoroutineClosure(..) + | ty::CoroutineWitness(..) + | ty::Dynamic(..) + | ty::Error(..) + | ty::Foreign(..) + | ty::Infer(..) + | ty::Param(..) + | ty::Placeholder(..) + | ty::UnsafeBinder(..) => None, + } + } + pub(crate) fn simplified_types() -> &'static SimplifiedTypes { use PrimitiveType::*; use ty::{FloatTy, IntTy, UintTy}; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 35212d480cfdd..e6c64ef8b4220 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -9,8 +9,7 @@ use std::cmp::Ordering; use std::fmt::{self, Display, Write}; -use std::iter::{self, once}; -use std::slice; +use std::{iter, slice}; use itertools::{Either, Itertools}; use rustc_abi::ExternAbi; @@ -434,27 +433,33 @@ fn generate_item_def_id_path( let tcx = cx.tcx(); let crate_name = tcx.crate_name(def_id.krate); + let mut prim = None; // No need to try to infer the actual parent item if it's not an associated item from the `impl` // block. if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - def_id = infcx + let ty = tcx.type_of(def_id); + let ty = infcx .at(&ObligationCause::dummy(), tcx.param_env(def_id)) - .query_normalize(ty::Binder::dummy( - tcx.type_of(def_id).instantiate_identity().skip_norm_wip(), - )) - .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)) - .ok() - .and_then(|normalized| normalized.skip_binder().ty_adt_def()) - .map(|adt| adt.did()) - .unwrap_or(def_id); + .query_normalize(ty::Binder::dummy(ty.instantiate_identity().skip_norm_wip())) + .map(|resolved| infcx.resolve_vars_if_possible(resolved.value).skip_binder()) + .unwrap_or(ty.skip_binder()); + if let Some(new_def_id) = ty.ty_adt_def().map(|adt| adt.did()) { + def_id = new_def_id; + } else { + prim = PrimitiveType::from_ty(ty); + } } - let relative = clean::inline::item_relative_path(tcx, def_id); - let fqp: Vec = once(crate_name).chain(relative).collect(); - - let shortty = ItemType::from_def_id(def_id, tcx); + let mut fqp = vec![crate_name]; + let shortty = if let Some(prim) = prim { + fqp.push(prim.as_sym()); + ItemType::Primitive + } else { + fqp.append(&mut clean::inline::item_relative_path(tcx, def_id)); + ItemType::from_def_id(def_id, tcx) + }; let module_fqp = to_module_fqp(shortty, &fqp); let (parts, is_absolute) = url_parts(cx.cache(), def_id, module_fqp, &cx.current)?; diff --git a/tests/rustdoc-html/jump-to-def/prim-method.rs b/tests/rustdoc-html/jump-to-def/prim-method.rs new file mode 100644 index 0000000000000..43f6592de5390 --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/prim-method.rs @@ -0,0 +1,16 @@ +// Checks that links to primitive types methods work. +// Regression test for . + +// ignore-tidy-linelength +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +//@ has 'src/foo/prim-method.rs.html' + +fn scope() { + //@ has - '//a[@href="{{channel}}/core/primitive.usize.html#method.saturating_add"]' 'saturating_add' + let _ = 0usize.saturating_add(1); + //@ has - '//a[@href="{{channel}}/core/primitive.bool.html#method.then_some"]' 'then_some' + let _ = false.then_some(()); +} From 0ff74c976a8e0014b1e394735696a8e6c1c594b8 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Sat, 23 May 2026 21:24:21 +0200 Subject: [PATCH 16/16] Fix Pieter-Louis Schoeman mailmap entry --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 4a3e39831e8a2..3fc567081c1ff 100644 --- a/.mailmap +++ b/.mailmap @@ -569,6 +569,7 @@ Philipp Matthias Schäfer phosphorus Pierre Krieger pierwill <19642016+pierwill@users.noreply.github.com> +Pieter-Louis Schoeman <127837395+P8L1@users.noreply.github.com> Pietro Albini Pietro Albini Pradyumna Rahul