From e5a67968e609c49472990768ddbc9547880490bb Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Thu, 21 May 2026 22:25:59 +0200 Subject: [PATCH] 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 f2fa6fd0ca3e..ab7e85a6aaba 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -290,6 +290,30 @@ fn clone_from(&mut self, source: &Self) /* 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 6122ab12ec35..d763640bc930 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -30,6 +30,8 @@ #[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 39402f78bb5e..386e77ae2bd3 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 000000000000..2b4791d2eb03 --- /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 000000000000..344f5d8670f6 --- /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 000000000000..4876fac2b8c1 --- /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 000000000000..733c8f2d2b21 --- /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 000000000000..a70ae3ade37d --- /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 000000000000..ac775db690a4 --- /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 000000000000..4292222d9751 --- /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)); +}