@@ -290,6 +290,90 @@ pub macro Clone($item:item) {
290290 /* compiler built-in */
291291}
292292
293+ /// A trait for types whose [`Clone`] operation creates another alias to the same
294+ /// logical resource or shared state.
295+ ///
296+ /// `Share` marks types where cloning creates another handle, reference, or alias
297+ /// to the same logical resource or shared state, rather than an independent owned
298+ /// value. The distinction is semantic, not cost-based: implementing `Share` does
299+ /// not merely mean that cloning is cheap, constant-time, allocation-free, or
300+ /// convenient.
301+ ///
302+ /// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone)
303+ /// for implementors, but communicates that the resulting value aliases the same
304+ /// underlying resource.
305+ ///
306+ /// Shared references, `Rc<T>`, `Arc<T>`, `Sender<T>`, and `SyncSender<T>` are
307+ /// examples of types that can be shared this way. Types such as `Vec<T>`,
308+ /// `String`, and `Box<T>` are not `Share` even though they implement `Clone`,
309+ /// because cloning them creates another owned value rather than another handle
310+ /// to the same logical resource.
311+ ///
312+ /// # Examples
313+ ///
314+ /// ```
315+ /// #![feature(share_trait)]
316+ ///
317+ /// use std::cell::Cell;
318+ /// use std::clone::Share;
319+ /// use std::rc::Rc;
320+ /// use std::sync::{
321+ /// Arc,
322+ /// atomic::{AtomicUsize, Ordering},
323+ /// };
324+ ///
325+ /// let value = 1;
326+ /// let reference = &value;
327+ /// assert!(std::ptr::eq(reference, reference.share()));
328+ ///
329+ /// let rc = Rc::new(Cell::new(2));
330+ /// let shared_rc = rc.share();
331+ /// assert!(Rc::ptr_eq(&rc, &shared_rc));
332+ /// shared_rc.set(3);
333+ /// assert_eq!(rc.get(), 3);
334+ ///
335+ /// let arc = Arc::new(AtomicUsize::new(4));
336+ /// let shared_arc = arc.share();
337+ /// assert!(Arc::ptr_eq(&arc, &shared_arc));
338+ /// shared_arc.store(5, Ordering::Relaxed);
339+ /// assert_eq!(arc.load(Ordering::Relaxed), 5);
340+ /// ```
341+ ///
342+ /// ```
343+ /// #![feature(share_trait)]
344+ ///
345+ /// use std::clone::Share;
346+ /// use std::sync::mpsc::{channel, sync_channel};
347+ ///
348+ /// let (sender, receiver) = channel();
349+ /// let shared_sender = sender.share();
350+ /// sender.send(1).unwrap();
351+ /// shared_sender.send(2).unwrap();
352+ ///
353+ /// let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()];
354+ /// received.sort();
355+ /// assert_eq!(received, [1, 2]);
356+ ///
357+ /// let (sync_sender, sync_receiver) = sync_channel(2);
358+ /// let shared_sync_sender = sync_sender.share();
359+ /// sync_sender.send(3).unwrap();
360+ /// shared_sync_sender.send(4).unwrap();
361+ ///
362+ /// let mut received = [sync_receiver.recv().unwrap(), sync_receiver.recv().unwrap()];
363+ /// received.sort();
364+ /// assert_eq!(received, [3, 4]);
365+ /// ```
366+ #[ unstable( feature = "share_trait" , issue = "156756" ) ]
367+ pub trait Share : Clone {
368+ /// Creates another alias to the same underlying resource or shared state.
369+ ///
370+ /// This is equivalent to calling [`Clone::clone`].
371+ #[ unstable( feature = "share_trait" , issue = "156756" ) ]
372+ fn share ( & self ) -> Self {
373+ Clone :: clone ( self )
374+ }
375+ }
376+
293377/// Trait for objects whose [`Clone`] impl is lightweight (e.g. reference-counted)
294378///
295379/// Cloning an object implementing this trait should in general:
@@ -601,7 +685,7 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr {
601685/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
602686/// in `rustc_trait_selection`.
603687mod impls {
604- use super :: TrivialClone ;
688+ use super :: { Share , TrivialClone } ;
605689 use crate :: marker:: PointeeSized ;
606690
607691 macro_rules! impl_clone {
@@ -689,6 +773,9 @@ mod impls {
689773 #[ rustc_const_unstable( feature = "const_clone" , issue = "142757" ) ]
690774 unsafe impl < T : PointeeSized > const TrivialClone for & T { }
691775
776+ #[ unstable( feature = "share_trait" , issue = "156756" ) ]
777+ impl < T : PointeeSized > Share for & T { }
778+
692779 /// Shared references can be cloned, but mutable references *cannot*!
693780 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
694781 impl < T : PointeeSized > !Clone for & mut T { }
0 commit comments