Skip to content

Commit d15d3f7

Browse files
authored
Rollup merge of rust-lang#134797 - spastorino:ergonomic-ref-counting-1, r=nikomatsakis
Ergonomic ref counting This is an experimental first version of ergonomic ref counting. This first version implements most of the RFC but doesn't implement any of the optimizations. This was left for following iterations. RFC: rust-lang/rfcs#3680 Tracking issue: rust-lang#132290 Project goal: rust-lang/rust-project-goals#107 r? ```@nikomatsakis```
2 parents dfca153 + 64dedc1 commit d15d3f7

File tree

9 files changed

+93
-2
lines changed

9 files changed

+93
-2
lines changed

Diff for: alloc/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
//! [`Rc`]: rc
5757
//! [`RefCell`]: core::cell
5858
59+
#![allow(incomplete_features)]
5960
#![allow(unused_attributes)]
6061
#![stable(feature = "alloc", since = "1.36.0")]
6162
#![doc(
@@ -113,6 +114,7 @@
113114
#![feature(deprecated_suggestion)]
114115
#![feature(deref_pure_trait)]
115116
#![feature(dispatch_from_dyn)]
117+
#![feature(ergonomic_clones)]
116118
#![feature(error_generic_member_access)]
117119
#![feature(exact_size_is_empty)]
118120
#![feature(extend_one)]

Diff for: alloc/src/rc.rs

+7
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ use core::any::Any;
245245
use core::cell::Cell;
246246
#[cfg(not(no_global_oom_handling))]
247247
use core::clone::CloneToUninit;
248+
use core::clone::UseCloned;
248249
use core::cmp::Ordering;
249250
use core::hash::{Hash, Hasher};
250251
use core::intrinsics::abort;
@@ -2333,6 +2334,9 @@ impl<T: ?Sized, A: Allocator + Clone> Clone for Rc<T, A> {
23332334
}
23342335
}
23352336

2337+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
2338+
impl<T: ?Sized, A: Allocator + Clone> UseCloned for Rc<T, A> {}
2339+
23362340
#[cfg(not(no_global_oom_handling))]
23372341
#[stable(feature = "rust1", since = "1.0.0")]
23382342
impl<T: Default> Default for Rc<T> {
@@ -3496,6 +3500,9 @@ impl<T: ?Sized, A: Allocator + Clone> Clone for Weak<T, A> {
34963500
}
34973501
}
34983502

3503+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
3504+
impl<T: ?Sized, A: Allocator + Clone> UseCloned for Weak<T, A> {}
3505+
34993506
#[stable(feature = "rc_weak", since = "1.4.0")]
35003507
impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
35013508
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

Diff for: alloc/src/sync.rs

+7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use core::any::Any;
1212
#[cfg(not(no_global_oom_handling))]
1313
use core::clone::CloneToUninit;
14+
use core::clone::UseCloned;
1415
use core::cmp::Ordering;
1516
use core::hash::{Hash, Hasher};
1617
use core::intrinsics::abort;
@@ -2197,6 +2198,9 @@ impl<T: ?Sized, A: Allocator + Clone> Clone for Arc<T, A> {
21972198
}
21982199
}
21992200

2201+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
2202+
impl<T: ?Sized, A: Allocator + Clone> UseCloned for Arc<T, A> {}
2203+
22002204
#[stable(feature = "rust1", since = "1.0.0")]
22012205
impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> {
22022206
type Target = T;
@@ -3158,6 +3162,9 @@ impl<T: ?Sized, A: Allocator + Clone> Clone for Weak<T, A> {
31583162
}
31593163
}
31603164

3165+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
3166+
impl<T: ?Sized, A: Allocator + Clone> UseCloned for Weak<T, A> {}
3167+
31613168
#[stable(feature = "downgraded_weak", since = "1.10.0")]
31623169
impl<T> Default for Weak<T> {
31633170
/// Constructs a new `Weak<T>`, without allocating memory.

Diff for: core/src/clone.rs

+53
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,59 @@ pub macro Clone($item:item) {
184184
/* compiler built-in */
185185
}
186186

187+
/// Trait for objects whose [`Clone`] impl is lightweight (e.g. reference-counted)
188+
///
189+
/// Cloning an object implementing this trait should in general:
190+
/// - be O(1) (constant) time regardless of the amount of data managed by the object,
191+
/// - not require a memory allocation,
192+
/// - not require copying more than roughly 64 bytes (a typical cache line size),
193+
/// - not block the current thread,
194+
/// - not have any semantic side effects (e.g. allocating a file descriptor), and
195+
/// - not have overhead larger than a couple of atomic operations.
196+
///
197+
/// The `UseCloned` trait does not provide a method; instead, it indicates that
198+
/// `Clone::clone` is lightweight, and allows the use of the `.use` syntax.
199+
///
200+
/// ## .use postfix syntax
201+
///
202+
/// Values can be `.use`d by adding `.use` postfix to the value you want to use.
203+
///
204+
/// ```ignore (this won't work until we land use)
205+
/// fn foo(f: Foo) {
206+
/// // if `Foo` implements `Copy` f would be copied into x.
207+
/// // if `Foo` implements `UseCloned` f would be cloned into x.
208+
/// // otherwise f would be moved into x.
209+
/// let x = f.use;
210+
/// // ...
211+
/// }
212+
/// ```
213+
///
214+
/// ## use closures
215+
///
216+
/// Use closures allow captured values to be automatically used.
217+
/// This is similar to have a closure that you would call `.use` over each captured value.
218+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
219+
#[cfg_attr(not(bootstrap), lang = "use_cloned")]
220+
pub trait UseCloned: Clone {
221+
// Empty.
222+
}
223+
224+
macro_rules! impl_use_cloned {
225+
($($t:ty)*) => {
226+
$(
227+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
228+
impl UseCloned for $t {}
229+
)*
230+
}
231+
}
232+
233+
impl_use_cloned! {
234+
usize u8 u16 u32 u64 u128
235+
isize i8 i16 i32 i64 i128
236+
f16 f32 f64 f128
237+
bool char
238+
}
239+
187240
// FIXME(aburka): these structs are used solely by #[derive] to
188241
// assert that every component of a type implements Clone or Copy.
189242
//

Diff for: core/src/num/bignum.rs

+2
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,8 @@ macro_rules! define_bignum {
404404
}
405405
}
406406

407+
impl crate::clone::UseCloned for $name {}
408+
407409
impl crate::fmt::Debug for $name {
408410
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
409411
let sz = if self.size < 1 { 1 } else { self.size };

Diff for: core/src/num/nonzero.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Definitions of integer that is known not to equal zero.
22
33
use super::{IntErrorKind, ParseIntError};
4+
use crate::clone::UseCloned;
45
use crate::cmp::Ordering;
56
use crate::hash::{Hash, Hasher};
67
use crate::marker::{Freeze, StructuralPartialEq};
@@ -182,6 +183,9 @@ where
182183
}
183184
}
184185

186+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
187+
impl<T> UseCloned for NonZero<T> where T: ZeroablePrimitive {}
188+
185189
#[stable(feature = "nonzero", since = "1.28.0")]
186190
impl<T> Copy for NonZero<T> where T: ZeroablePrimitive {}
187191

Diff for: core/src/option.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2050,6 +2050,9 @@ where
20502050
}
20512051
}
20522052

2053+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
2054+
impl<T> crate::clone::UseCloned for Option<T> where T: crate::clone::UseCloned {}
2055+
20532056
#[stable(feature = "rust1", since = "1.0.0")]
20542057
impl<T> Default for Option<T> {
20552058
/// Returns [`None`][Option::None].

Diff for: core/src/result.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,14 @@ where
17441744
}
17451745
}
17461746

1747+
#[unstable(feature = "ergonomic_clones", issue = "132290")]
1748+
impl<T, E> crate::clone::UseCloned for Result<T, E>
1749+
where
1750+
T: crate::clone::UseCloned,
1751+
E: crate::clone::UseCloned,
1752+
{
1753+
}
1754+
17471755
#[stable(feature = "rust1", since = "1.0.0")]
17481756
impl<T, E> IntoIterator for Result<T, E> {
17491757
type Item = T;

Diff for: std/src/keyword_docs.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -2121,8 +2121,8 @@ mod unsafe_keyword {}
21212121

21222122
#[doc(keyword = "use")]
21232123
//
2124-
/// Import or rename items from other crates or modules, or specify precise capturing
2125-
/// with `use<..>`.
2124+
/// Import or rename items from other crates or modules, use values under ergonomic clones
2125+
/// semantic, or specify precise capturing with `use<..>`.
21262126
///
21272127
/// ## Importing items
21282128
///
@@ -2205,6 +2205,11 @@ mod unsafe_keyword {}
22052205
///
22062206
/// For more details about precise capturing, see the [Reference][ref-impl-trait].
22072207
///
2208+
/// ## Ergonomic clones
2209+
///
2210+
/// Use a values, copying its content if the value implements `Copy`, cloning the contents if the
2211+
/// value implements `UseCloned` or moving it otherwise.
2212+
///
22082213
/// [`crate`]: keyword.crate.html
22092214
/// [`self`]: keyword.self.html
22102215
/// [`super`]: keyword.super.html

0 commit comments

Comments
 (0)