Skip to content

Tracking Issue for Share trait #156756

@P8L1

Description

@P8L1

Tracking Issue for Share trait

This is a tracking issue for the unstable Share trait, proposed as part of the 2026 ergonomic ref-counting project goal.

Project goal:

The feature gate is not yet confirmed. Possible options include:

#![feature(share_trait)]

or reusing the existing ergonomic ref-counting gate:

#![feature(ergonomic_clones)]

cc @nikomatsakis

Summary

The Share trait identifies types where cloning creates another alias, handle, or reference to the same underlying value.

The intended distinction is semantic, not operational:

  • Share means “clone-as-alias”.
  • Share does not merely mean “cheap clone”, “O(1) clone”, or “allocation-free clone”.

For implementors, share() would be equivalent to clone(), but it communicates that the old and new values are connected to the same underlying value or resource rather than being independent owned copies.

A possible minimal shape is:

pub trait Share: Clone {
    fn share(&self) -> Self {
        Clone::clone(self)
    }
}

The exact public location, feature gate, default method body, and initial impl set still need confirmation.

Scope

This tracking issue is only for the Share trait part of ergonomic ref-counting.

Candidate initial impls

The project-goal sketch lists the following initial candidates:

impl<T: ?Sized> Share for Arc<T> {}
impl<T: ?Sized> Share for Rc<T> {}
impl<T: ?Sized> Share for &T {}
impl<T> Share for std::sync::mpsc::Sender<T> {}

Additional sender-like candidates to evaluate:

impl<T> Share for std::sync::mpsc::SyncSender<T> {}

These should be confirmed before implementation, especially the sender-like impl set.

Non-examples

The following should not implement Share, because cloning creates an independent owned value rather than another alias/handle/reference to the same underlying value:

  • Vec<T>
  • String
  • Box<T>
  • HashMap<K, V>
  • BTreeMap<K, V>
  • owned arrays
  • other owned collection types where clone() creates independent owned storage

Steps

  • Confirm feature gate.

    • Decide whether to use a new share_trait feature gate.
    • Decide whether to reuse ergonomic_clones instead.
    • Connect the feature gate to the correct tracking issue.
  • Decide public location and module organization.

    • Confirm whether Share should live near Clone, for example in core::clone.
    • Confirm public re-export expectations from core, alloc, and std.
    • Confirm that Share should not be added to the prelude initially.
  • Add the unstable trait API.

    • Add pub trait Share: Clone.
    • Add fn share(&self) -> Self.
    • Confirm whether the default body should use Clone::clone(self) or self.clone().
    • Add unstable attributes and feature-gate diagnostics.
  • Add Share for shared references.

    • Add impl<T: ?Sized> Share for &T {}.
    • Add tests for .share() on shared references.
    • Confirm that mutable references are not candidates.
  • Add Share for Rc<T>.

    • Add impl<T: ?Sized> Share for Rc<T> {}.
    • Add tests showing that sharing preserves allocation identity, for example with Rc::ptr_eq.
    • Add tests showing observable shared state where appropriate.
  • Add Share for Arc<T>.

    • Add impl<T: ?Sized> Share for Arc<T> {}.
    • Add tests showing that sharing preserves allocation identity, for example with Arc::ptr_eq.
    • Add tests showing observable shared state where appropriate.
  • Evaluate channel sender impls.

    • Confirm whether std::sync::mpsc::Sender<T> should implement Share.
    • Confirm whether std::sync::mpsc::SyncSender<T> should implement Share.
    • Add tests showing that both handles send to the same receiver.
  • Audit impl

  • Add tests.

    • Feature-gate tests.
    • Method-availability tests.
    • Positive impl tests for accepted candidates.
    • Negative tests for non-implementors if desired.
    • Documentation tests where appropriate.
  • Add documentation.

    • Document that Share is for clone-as-alias types.
    • Document that share() is equivalent to clone() for implementors.
    • Document that the distinction is semantic rather than cost-based.
    • Include examples such as Arc<T>, Rc<T>, shared references, and channel senders.
    • Include non-examples such as Vec<T>, String, and Box<T>.
  • Stabilization PR, after implementation experience and API review.

Unresolved questions

  • Should the feature use a new share_trait gate, or reuse ergonomic_clones?
  • Where should Share live publicly?
  • Which sender-like types should implement Share?
  • Should Share remain out of the prelude during experimentation?
  • Should the default method body use Clone::clone(self)?
  • Should the trait docs explicitly say that Share is semantic, not cost-based?
  • Are there any object-safety or dyn-compatibility concerns worth documenting?
  • Should Weak<T> for Rc/Arc be considered later, or explicitly left out?

Implementation history

  • Initial tracking issue: this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions