add a TrivialClone implementation when deriving both Clone and Copy

This commit is contained in:
joboet 2025-01-17 16:19:10 +01:00
parent 5fb5861765
commit e4e765b1f6
No known key found for this signature in database
GPG key ID: 704E0149B0194B3C
17 changed files with 82 additions and 16 deletions

View file

@ -1,4 +1,4 @@
use rustc_ast::MetaItem;
use rustc_ast::{MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::Span;
@ -24,6 +24,7 @@ pub(crate) fn expand_deriving_copy(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push);
@ -48,6 +49,7 @@ pub(crate) fn expand_deriving_const_param_ty(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push);

View file

@ -1,7 +1,7 @@
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, Safety, VariantData};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Ident, Span, kw, sym};
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};
use crate::deriving::generic::ty::*;
@ -68,6 +68,26 @@ pub(crate) fn expand_deriving_clone(
_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
}
// If the clone method is just copying the value, also mark the type as
// `TrivialClone` to allow some library optimizations.
if is_simple {
let trivial_def = TraitDef {
span,
path: path_std!(clone::TrivialClone),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: true,
additional_bounds: bounds.clone(),
supports_unions: true,
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Unsafe(DUMMY_SP),
};
trivial_def.expand_ext(cx, mitem, item, push, true);
}
let trait_def = TraitDef {
span,
path: path_std!(clone::Clone),
@ -88,6 +108,7 @@ pub(crate) fn expand_deriving_clone(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand_ext(cx, mitem, item, push, is_simple)

View file

@ -1,4 +1,4 @@
use rustc_ast::{self as ast, MetaItem};
use rustc_ast::{self as ast, MetaItem, Safety};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Span, sym};
@ -44,6 +44,7 @@ pub(crate) fn expand_deriving_eq(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand_ext(cx, mitem, item, push, true)
}

View file

@ -1,4 +1,4 @@
use rustc_ast::MetaItem;
use rustc_ast::{MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Ident, Span, sym};
use thin_vec::thin_vec;
@ -35,6 +35,7 @@ pub(crate) fn expand_deriving_ord(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push)

View file

@ -1,4 +1,4 @@
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Span, sym};
use thin_vec::thin_vec;
@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq(
associated_types: Vec::new(),
is_const: false,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
structural_trait_def.expand(cx, mitem, item, push);
@ -59,6 +60,7 @@ pub(crate) fn expand_deriving_partial_eq(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -1,4 +1,4 @@
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Ident, Span, sym};
use thin_vec::thin_vec;
@ -65,6 +65,7 @@ pub(crate) fn expand_deriving_partial_ord(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -1,4 +1,4 @@
use rustc_ast::{self as ast, EnumDef, MetaItem};
use rustc_ast::{self as ast, EnumDef, MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_session::config::FmtDebug;
use rustc_span::{Ident, Span, Symbol, sym};
@ -42,6 +42,7 @@ pub(crate) fn expand_deriving_debug(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -1,8 +1,7 @@
use core::ops::ControlFlow;
use rustc_ast as ast;
use rustc_ast::visit::visit_opt;
use rustc_ast::{EnumDef, VariantData, attr};
use rustc_ast::{self as ast, EnumDef, Safety, VariantData, attr};
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use smallvec::SmallVec;
@ -52,6 +51,7 @@ pub(crate) fn expand_deriving_default(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -1,5 +1,5 @@
use rustc_ast as ast;
use rustc_ast::{ItemKind, VariantData};
use rustc_ast::{ItemKind, Safety, VariantData};
use rustc_errors::MultiSpan;
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
use rustc_span::{Ident, Span, kw, sym};
@ -127,6 +127,7 @@ pub(crate) fn expand_deriving_from(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
from_trait_def.expand(cx, mitem, annotatable, push);

View file

@ -225,6 +225,9 @@ pub(crate) struct TraitDef<'a> {
pub is_const: bool,
pub is_staged_api_crate: bool,
/// The safety of the `impl`.
pub safety: Safety,
}
pub(crate) struct MethodDef<'a> {
@ -832,7 +835,7 @@ impl<'a> TraitDef<'a> {
ast::ItemKind::Impl(ast::Impl {
generics: trait_generics,
of_trait: Some(Box::new(ast::TraitImplHeader {
safety: ast::Safety::Default,
safety: self.safety,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
constness: if self.is_const {

View file

@ -1,4 +1,4 @@
use rustc_ast::{MetaItem, Mutability};
use rustc_ast::{MetaItem, Mutability, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Span, sym};
use thin_vec::thin_vec;
@ -42,6 +42,7 @@ pub(crate) fn expand_deriving_hash(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
};
hash_trait_def.expand(cx, mitem, item, push);

View file

@ -372,6 +372,7 @@ symbols! {
ToString,
TokenStream,
Trait,
TrivialClone,
Try,
TryCaptureGeneric,
TryCapturePrintable,

View file

@ -280,7 +280,7 @@ pub const unsafe trait TrivialClone: [const] Clone {}
/// Derive macro generating an impl of the trait `Clone`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
#[allow_internal_unstable(core_intrinsics, derive_clone_copy, trivial_clone)]
pub macro Clone($item:item) {
/* compiler built-in */
}

View file

@ -6,6 +6,7 @@
#[derive(Copy, Clone)]
//~^ ERROR conflicting implementations of trait `Clone` for type `E`
//~| ERROR conflicting implementations of trait `Copy` for type `E`
//~| ERROR conflicting implementations of trait `TrivialClone` for type `E`
enum E {}
fn main() {}

View file

@ -6,6 +6,16 @@ LL | #[derive(Copy, Clone)]
LL | #[derive(Copy, Clone)]
| ^^^^ conflicting implementation for `E`
error[E0119]: conflicting implementations of trait `TrivialClone` for type `E`
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
|
LL | #[derive(Copy, Clone)]
| ----- first implementation here
LL | #[derive(Copy, Clone)]
| ^^^^^ conflicting implementation for `E`
|
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0119]: conflicting implementations of trait `Clone` for type `E`
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
|
@ -14,6 +24,6 @@ LL | #[derive(Copy, Clone)]
LL | #[derive(Copy, Clone)]
| ^^^^^ conflicting implementation for `E`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0119`.

View file

@ -28,6 +28,8 @@ use std::from::From;
// Empty struct.
struct Empty;
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Empty { }
#[automatically_derived]
impl ::core::clone::Clone for Empty {
#[inline]
fn clone(&self) -> Empty { *self }
@ -88,6 +90,8 @@ struct Point {
y: u32,
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Point { }
#[automatically_derived]
impl ::core::clone::Clone for Point {
#[inline]
fn clone(&self) -> Point {
@ -173,6 +177,8 @@ struct PackedPoint {
y: u32,
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for PackedPoint { }
#[automatically_derived]
impl ::core::clone::Clone for PackedPoint {
#[inline]
fn clone(&self) -> PackedPoint {
@ -254,6 +260,8 @@ impl ::core::cmp::Ord for PackedPoint {
struct TupleSingleField(u32);
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for TupleSingleField { }
#[automatically_derived]
impl ::core::clone::Clone for TupleSingleField {
#[inline]
fn clone(&self) -> TupleSingleField {
@ -326,6 +334,8 @@ struct SingleField {
foo: bool,
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for SingleField { }
#[automatically_derived]
impl ::core::clone::Clone for SingleField {
#[inline]
fn clone(&self) -> SingleField {
@ -407,6 +417,8 @@ struct Big {
b8: u32,
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Big { }
#[automatically_derived]
impl ::core::clone::Clone for Big {
#[inline]
fn clone(&self) -> Big {
@ -1007,6 +1019,8 @@ impl<T: ::core::cmp::Ord + ::core::marker::Copy + Trait, U: ::core::cmp::Ord +
// An empty enum.
enum Enum0 {}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Enum0 { }
#[automatically_derived]
impl ::core::clone::Clone for Enum0 {
#[inline]
fn clone(&self) -> Enum0 { *self }
@ -1202,6 +1216,8 @@ enum Fieldless {
C,
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Fieldless { }
#[automatically_derived]
impl ::core::clone::Clone for Fieldless {
#[inline]
fn clone(&self) -> Fieldless { *self }
@ -1284,6 +1300,8 @@ enum Mixed {
},
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Mixed { }
#[automatically_derived]
impl ::core::clone::Clone for Mixed {
#[inline]
fn clone(&self) -> Mixed {
@ -1752,6 +1770,8 @@ pub union Union {
pub i: i32,
}
#[automatically_derived]
unsafe impl ::core::clone::TrivialClone for Union { }
#[automatically_derived]
impl ::core::clone::Clone for Union {
#[inline]
fn clone(&self) -> Union {

View file

@ -2,7 +2,7 @@ macro-stats ====================================================================
macro-stats MACRO EXPANSION STATS: macro_stats
macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes
macro-stats -----------------------------------------------------------------------------------
macro-stats #[derive(Clone)] 8 64 8.0 1_788 223.5
macro-stats #[derive(Clone)] 8 66 8.2 1_864 233.0
macro-stats #[derive(PartialOrd)] 1 17 17.0 675 675.0
macro-stats #[derive(Hash)] 2 17 8.5 577 288.5
macro-stats q! 1 26 26.0 519 519.0