Skip to content

Commit 5b1b3ee

Browse files
committed
add a TrivialClone implementation when deriving both Clone and Copy
1 parent 307f603 commit 5b1b3ee

17 files changed

+81
-17
lines changed

compiler/rustc_builtin_macros/src/deriving/bounds.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::MetaItem;
1+
use rustc_ast::{MetaItem, Safety};
22
use rustc_expand::base::{Annotatable, ExtCtxt};
33
use rustc_span::Span;
44

@@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy(
2323
methods: Vec::new(),
2424
associated_types: Vec::new(),
2525
is_const,
26+
safety: Safety::Default,
2627
};
2728

2829
trait_def.expand(cx, mitem, item, push);
@@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty(
4647
methods: Vec::new(),
4748
associated_types: Vec::new(),
4849
is_const,
50+
safety: Safety::Default,
4951
};
5052

5153
trait_def.expand(cx, mitem, item, push);
@@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty(
6062
methods: Vec::new(),
6163
associated_types: Vec::new(),
6264
is_const,
65+
safety: Safety::Default,
6366
};
6467

6568
trait_def.expand(cx, mitem, item, push);
@@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty(
8386
methods: Vec::new(),
8487
associated_types: Vec::new(),
8588
is_const,
89+
safety: Safety::Default,
8690
};
8791

8892
trait_def.expand(cx, mitem, item, push);

compiler/rustc_builtin_macros/src/deriving/clone.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
1+
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, Safety, VariantData};
22
use rustc_data_structures::fx::FxHashSet;
33
use rustc_expand::base::{Annotatable, ExtCtxt};
4-
use rustc_span::{Ident, Span, kw, sym};
4+
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
55
use thin_vec::{ThinVec, thin_vec};
66

77
use crate::deriving::generic::ty::*;
@@ -68,6 +68,25 @@ pub(crate) fn expand_deriving_clone(
6868
_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
6969
}
7070

71+
// If the clone method is just copying the value, also mark the type as
72+
// `TrivialClone` to allow some library optimizations.
73+
if is_simple {
74+
let trivial_def = TraitDef {
75+
span,
76+
path: path_std!(clone::TrivialClone),
77+
skip_path_as_bound: false,
78+
needs_copy_as_bound_if_packed: true,
79+
additional_bounds: bounds.clone(),
80+
supports_unions: true,
81+
methods: Vec::new(),
82+
associated_types: Vec::new(),
83+
is_const,
84+
safety: Safety::Unsafe(DUMMY_SP),
85+
};
86+
87+
trivial_def.expand_ext(cx, mitem, item, push, true);
88+
}
89+
7190
let trait_def = TraitDef {
7291
span,
7392
path: path_std!(clone::Clone),
@@ -87,6 +106,7 @@ pub(crate) fn expand_deriving_clone(
87106
}],
88107
associated_types: Vec::new(),
89108
is_const,
109+
safety: Safety::Default,
90110
};
91111

92112
trait_def.expand_ext(cx, mitem, item, push, is_simple)

compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::{self as ast, MetaItem};
1+
use rustc_ast::{self as ast, MetaItem, Safety};
22
use rustc_data_structures::fx::FxHashSet;
33
use rustc_expand::base::{Annotatable, ExtCtxt};
44
use rustc_span::{Span, sym};
@@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq(
4343
}],
4444
associated_types: Vec::new(),
4545
is_const,
46+
safety: Safety::Default,
4647
};
4748
trait_def.expand_ext(cx, mitem, item, push, true)
4849
}

compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::MetaItem;
1+
use rustc_ast::{MetaItem, Safety};
22
use rustc_expand::base::{Annotatable, ExtCtxt};
33
use rustc_span::{Ident, Span, sym};
44
use thin_vec::thin_vec;
@@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord(
3434
}],
3535
associated_types: Vec::new(),
3636
is_const,
37+
safety: Safety::Default,
3738
};
3839

3940
trait_def.expand(cx, mitem, item, push)

compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_ast::ptr::P;
2-
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
2+
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability, Safety};
33
use rustc_expand::base::{Annotatable, ExtCtxt};
44
use rustc_span::{Span, sym};
55
use thin_vec::thin_vec;
@@ -84,6 +84,7 @@ pub(crate) fn expand_deriving_partial_eq(
8484
methods: Vec::new(),
8585
associated_types: Vec::new(),
8686
is_const: false,
87+
safety: Safety::Default,
8788
};
8889
structural_trait_def.expand(cx, mitem, item, push);
8990

@@ -110,6 +111,7 @@ pub(crate) fn expand_deriving_partial_eq(
110111
methods,
111112
associated_types: Vec::new(),
112113
is_const,
114+
safety: Safety::Default,
113115
};
114116
trait_def.expand(cx, mitem, item, push)
115117
}

compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
1+
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety};
22
use rustc_expand::base::{Annotatable, ExtCtxt};
33
use rustc_span::{Ident, Span, sym};
44
use thin_vec::thin_vec;
@@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord(
6464
methods: vec![partial_cmp_def],
6565
associated_types: Vec::new(),
6666
is_const,
67+
safety: Safety::Default,
6768
};
6869
trait_def.expand(cx, mitem, item, push)
6970
}

compiler/rustc_builtin_macros/src/deriving/debug.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::{self as ast, EnumDef, MetaItem};
1+
use rustc_ast::{self as ast, EnumDef, MetaItem, Safety};
22
use rustc_expand::base::{Annotatable, ExtCtxt};
33
use rustc_session::config::FmtDebug;
44
use rustc_span::{Ident, Span, Symbol, sym};
@@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug(
4141
}],
4242
associated_types: Vec::new(),
4343
is_const,
44+
safety: Safety::Default,
4445
};
4546
trait_def.expand(cx, mitem, item, push)
4647
}

compiler/rustc_builtin_macros/src/deriving/decodable.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more.
22
33
use rustc_ast::ptr::P;
4-
use rustc_ast::{self as ast, Expr, MetaItem, Mutability};
4+
use rustc_ast::{self as ast, Expr, MetaItem, Mutability, Safety};
55
use rustc_expand::base::{Annotatable, ExtCtxt};
66
use rustc_span::{Ident, Span, Symbol, sym};
77
use thin_vec::{ThinVec, thin_vec};
@@ -58,6 +58,7 @@ pub(crate) fn expand_deriving_rustc_decodable(
5858
}],
5959
associated_types: Vec::new(),
6060
is_const,
61+
safety: Safety::Default,
6162
};
6263

6364
trait_def.expand(cx, mitem, item, push)

compiler/rustc_builtin_macros/src/deriving/default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use core::ops::ControlFlow;
22

3-
use rustc_ast as ast;
43
use rustc_ast::visit::visit_opt;
5-
use rustc_ast::{EnumDef, VariantData, attr};
4+
use rustc_ast::{self as ast, EnumDef, Safety, VariantData, attr};
65
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
76
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
87
use smallvec::SmallVec;
@@ -51,6 +50,7 @@ pub(crate) fn expand_deriving_default(
5150
}],
5251
associated_types: Vec::new(),
5352
is_const,
53+
safety: Safety::Default,
5454
};
5555
trait_def.expand(cx, mitem, item, push)
5656
}

compiler/rustc_builtin_macros/src/deriving/encodable.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
//! }
8686
//! ```
8787
88-
use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability};
88+
use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability, Safety};
8989
use rustc_expand::base::{Annotatable, ExtCtxt};
9090
use rustc_span::{Ident, Span, Symbol, sym};
9191
use thin_vec::{ThinVec, thin_vec};
@@ -142,6 +142,7 @@ pub(crate) fn expand_deriving_rustc_encodable(
142142
}],
143143
associated_types: Vec::new(),
144144
is_const,
145+
safety: Safety::Default,
145146
};
146147

147148
trait_def.expand(cx, mitem, item, push)

compiler/rustc_builtin_macros/src/deriving/generic/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ pub(crate) use SubstructureFields::*;
183183
use rustc_ast::ptr::P;
184184
use rustc_ast::{
185185
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
186-
Generics, Mutability, PatKind, VariantData,
186+
Generics, Mutability, PatKind, Safety, VariantData,
187187
};
188188
use rustc_attr_parsing as attr;
189189
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -220,6 +220,9 @@ pub(crate) struct TraitDef<'a> {
220220
pub associated_types: Vec<(Ident, Ty)>,
221221

222222
pub is_const: bool,
223+
224+
/// The safety of the `impl`.
225+
pub safety: Safety,
223226
}
224227

225228
pub(crate) struct MethodDef<'a> {
@@ -788,7 +791,7 @@ impl<'a> TraitDef<'a> {
788791
Ident::empty(),
789792
attrs,
790793
ast::ItemKind::Impl(Box::new(ast::Impl {
791-
safety: ast::Safety::Default,
794+
safety: self.safety,
792795
polarity: ast::ImplPolarity::Positive,
793796
defaultness: ast::Defaultness::Final,
794797
constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },

compiler/rustc_builtin_macros/src/deriving/hash.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::{MetaItem, Mutability};
1+
use rustc_ast::{MetaItem, Mutability, Safety};
22
use rustc_expand::base::{Annotatable, ExtCtxt};
33
use rustc_span::{Span, sym};
44
use thin_vec::thin_vec;
@@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash(
4141
}],
4242
associated_types: Vec::new(),
4343
is_const,
44+
safety: Safety::Default,
4445
};
4546

4647
hash_trait_def.expand(cx, mitem, item, push);

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ symbols! {
342342
ToString,
343343
TokenStream,
344344
Trait,
345+
TrivialClone,
345346
Try,
346347
TryCaptureGeneric,
347348
TryCapturePrintable,

library/core/src/clone.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ pub unsafe trait TrivialClone: Clone {}
205205
/// Derive macro generating an impl of the trait `Clone`.
206206
#[rustc_builtin_macro]
207207
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
208-
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
208+
#[allow_internal_unstable(core_intrinsics, derive_clone_copy, trivial_clone)]
209209
pub macro Clone($item:item) {
210210
/* compiler built-in */
211211
}

tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#[derive(Copy, Clone)]
77
//~^ ERROR conflicting implementations of trait `Clone` for type `E`
88
//~| ERROR conflicting implementations of trait `Copy` for type `E`
9+
//~| ERROR conflicting implementations of trait `TrivialClone` for type `E`
910
enum E {}
1011

1112
fn main() {}

tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ LL | #[derive(Copy, Clone)]
88
|
99
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
1010

11+
error[E0119]: conflicting implementations of trait `TrivialClone` for type `E`
12+
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
13+
|
14+
LL | #[derive(Copy, Clone)]
15+
| ----- first implementation here
16+
LL | #[derive(Copy, Clone)]
17+
| ^^^^^ conflicting implementation for `E`
18+
|
19+
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
1121
error[E0119]: conflicting implementations of trait `Clone` for type `E`
1222
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
1323
|
@@ -18,6 +28,6 @@ LL | #[derive(Copy, Clone)]
1828
|
1929
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
2030

21-
error: aborting due to 2 previous errors
31+
error: aborting due to 3 previous errors
2232

2333
For more information about this error, try `rustc --explain E0119`.

tests/ui/deriving/deriving-all-codegen.stdout

+16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ extern crate std;
2525
// Empty struct.
2626
struct Empty;
2727
#[automatically_derived]
28+
unsafe impl ::core::clone::TrivialClone for Empty { }
29+
#[automatically_derived]
2830
impl ::core::clone::Clone for Empty {
2931
#[inline]
3032
fn clone(&self) -> Empty { *self }
@@ -85,6 +87,8 @@ struct Point {
8587
y: u32,
8688
}
8789
#[automatically_derived]
90+
unsafe impl ::core::clone::TrivialClone for Point { }
91+
#[automatically_derived]
8892
impl ::core::clone::Clone for Point {
8993
#[inline]
9094
fn clone(&self) -> Point {
@@ -170,6 +174,8 @@ struct PackedPoint {
170174
y: u32,
171175
}
172176
#[automatically_derived]
177+
unsafe impl ::core::clone::TrivialClone for PackedPoint { }
178+
#[automatically_derived]
173179
impl ::core::clone::Clone for PackedPoint {
174180
#[inline]
175181
fn clone(&self) -> PackedPoint {
@@ -262,6 +268,8 @@ struct Big {
262268
b8: u32,
263269
}
264270
#[automatically_derived]
271+
unsafe impl ::core::clone::TrivialClone for Big { }
272+
#[automatically_derived]
265273
impl ::core::clone::Clone for Big {
266274
#[inline]
267275
fn clone(&self) -> Big {
@@ -763,6 +771,8 @@ impl<T: ::core::cmp::Ord + ::core::marker::Copy + Trait, U: ::core::cmp::Ord +
763771
// An empty enum.
764772
enum Enum0 {}
765773
#[automatically_derived]
774+
unsafe impl ::core::clone::TrivialClone for Enum0 { }
775+
#[automatically_derived]
766776
impl ::core::clone::Clone for Enum0 {
767777
#[inline]
768778
fn clone(&self) -> Enum0 { *self }
@@ -958,6 +968,8 @@ enum Fieldless {
958968
C,
959969
}
960970
#[automatically_derived]
971+
unsafe impl ::core::clone::TrivialClone for Fieldless { }
972+
#[automatically_derived]
961973
impl ::core::clone::Clone for Fieldless {
962974
#[inline]
963975
fn clone(&self) -> Fieldless { *self }
@@ -1040,6 +1052,8 @@ enum Mixed {
10401052
},
10411053
}
10421054
#[automatically_derived]
1055+
unsafe impl ::core::clone::TrivialClone for Mixed { }
1056+
#[automatically_derived]
10431057
impl ::core::clone::Clone for Mixed {
10441058
#[inline]
10451059
fn clone(&self) -> Mixed {
@@ -1437,6 +1451,8 @@ pub union Union {
14371451
pub i: i32,
14381452
}
14391453
#[automatically_derived]
1454+
unsafe impl ::core::clone::TrivialClone for Union { }
1455+
#[automatically_derived]
14401456
impl ::core::clone::Clone for Union {
14411457
#[inline]
14421458
fn clone(&self) -> Union {

0 commit comments

Comments
 (0)