Skip to content
6 changes: 5 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/bounds.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_ast::MetaItem;
use rustc_ast::{MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::Span;

Expand All @@ -24,6 +24,8 @@ pub(crate) fn expand_deriving_copy(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};

trait_def.expand(cx, mitem, item, push);
Expand All @@ -48,6 +50,8 @@ 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,
document: true,
};

trait_def.expand(cx, mitem, item, push);
Expand Down
29 changes: 27 additions & 2 deletions compiler/rustc_builtin_macros/src/deriving/clone.rs
Original file line number Diff line number Diff line change
@@ -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::*;
Expand Down Expand Up @@ -68,6 +68,29 @@ 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),
// `TrivialClone` is not part of an API guarantee, so it shouldn't
// appear in rustdoc output.
document: false,
};

trivial_def.expand_ext(cx, mitem, item, push, true);
}

let trait_def = TraitDef {
span,
path: path_std!(clone::Clone),
Expand All @@ -88,6 +111,8 @@ pub(crate) fn expand_deriving_clone(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};

trait_def.expand_ext(cx, mitem, item, push, is_simple)
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -44,6 +44,8 @@ pub(crate) fn expand_deriving_eq(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand_ext(cx, mitem, item, push, true)
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -35,6 +35,8 @@ pub(crate) fn expand_deriving_ord(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};

trait_def.expand(cx, mitem, item, push)
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -30,6 +30,8 @@ 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,
document: true,
};
structural_trait_def.expand(cx, mitem, item, push);

Expand Down Expand Up @@ -59,6 +61,8 @@ 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,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -65,6 +65,8 @@ 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,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/debug.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -42,6 +42,8 @@ pub(crate) fn expand_deriving_debug(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_builtin_macros/src/deriving/default.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -52,6 +51,8 @@ pub(crate) fn expand_deriving_default(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/from.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -127,6 +127,8 @@ pub(crate) fn expand_deriving_from(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};

from_trait_def.expand(cx, mitem, annotatable, push);
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,12 @@ pub(crate) struct TraitDef<'a> {
pub is_const: bool,

pub is_staged_api_crate: bool,

/// The safety of the `impl`.
pub safety: Safety,

/// Whether the added `impl` should appear in rustdoc output.
pub document: bool,
}

pub(crate) struct MethodDef<'a> {
Expand Down Expand Up @@ -826,13 +832,17 @@ impl<'a> TraitDef<'a> {
)
}

if !self.document {
attrs.push(cx.attr_nested_word(sym::doc, sym::hidden, self.span));
}

cx.item(
self.span,
attrs,
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 {
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/hash.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -42,6 +42,8 @@ pub(crate) fn expand_deriving_hash(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};

hash_trait_def.expand(cx, mitem, item, push);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ language_item_table! {
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
CloneFn, sym::clone_fn, clone_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
UseCloned, sym::use_cloned, use_cloned_trait, Target::Trait, GenericRequirement::None;
TrivialClone, sym::trivial_clone, trivial_clone_trait, Target::Trait, GenericRequirement::None;
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
/// The associated item of the `DiscriminantKind` trait.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ bidirectional_lang_item_map! {
PointeeTrait,
Sized,
TransmuteTrait,
TrivialClone,
Tuple,
Unpin,
Unsize,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,9 +547,11 @@ where
Some(SolverTraitLangItem::PointeeSized) => {
unreachable!("`PointeeSized` is removed during lowering");
}
Some(SolverTraitLangItem::Copy | SolverTraitLangItem::Clone) => {
G::consider_builtin_copy_clone_candidate(self, goal)
}
Some(
SolverTraitLangItem::Copy
| SolverTraitLangItem::Clone
| SolverTraitLangItem::TrivialClone,
) => G::consider_builtin_copy_clone_candidate(self, goal),
Some(SolverTraitLangItem::Fn) => {
G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ symbols! {
ToString,
TokenStream,
Trait,
TrivialClone,
Try,
TryCaptureGeneric,
TryCapturePrintable,
Expand Down Expand Up @@ -2270,6 +2271,7 @@ symbols! {
transparent_enums,
transparent_unions,
trivial_bounds,
trivial_clone,
truncf16,
truncf32,
truncf64,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

let lang_item = tcx.as_lang_item(def_id);
match lang_item {
Some(LangItem::Copy | LangItem::Clone) => {
Some(LangItem::Copy | LangItem::Clone | LangItem::TrivialClone) => {
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());

// User-defined copy impls are permitted, but only for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Some(LangItem::PointeeSized) => {
bug!("`PointeeSized` is removing during lowering");
}
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(self_ty),
Some(LangItem::Copy | LangItem::Clone | LangItem::TrivialClone) => {
self.copy_clone_conditions(self_ty)
}
Some(LangItem::FusedIterator) => {
if self.coroutine_is_gen(self_ty) {
ty::Binder::dummy(vec![])
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_type_ir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub enum SolverTraitLangItem {
PointeeTrait,
Sized,
TransmuteTrait,
TrivialClone,
Tuple,
Unpin,
Unsize,
Expand Down
6 changes: 5 additions & 1 deletion library/alloc/src/boxed/convert.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use core::any::Any;
#[cfg(not(no_global_oom_handling))]
use core::clone::TrivialClone;
use core::error::Error;
use core::mem;
use core::pin::Pin;
Expand Down Expand Up @@ -75,11 +77,13 @@ impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
}

#[cfg(not(no_global_oom_handling))]
impl<T: Copy> BoxFromSlice<T> for Box<[T]> {
impl<T: TrivialClone> BoxFromSlice<T> for Box<[T]> {
#[inline]
fn from_slice(slice: &[T]) -> Self {
let len = slice.len();
let buf = RawVec::with_capacity(len);
// SAFETY: since `T` implements `TrivialClone`, this is sound and
// equivalent to the above.
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box(slice.len()).assume_init()
Expand Down
4 changes: 3 additions & 1 deletion library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#![stable(feature = "rust1", since = "1.0.0")]

#[cfg(not(no_global_oom_handling))]
use core::clone::TrivialClone;
use core::cmp::{self, Ordering};
use core::hash::{Hash, Hasher};
use core::iter::{ByRefSized, repeat_n, repeat_with};
Expand Down Expand Up @@ -3419,7 +3421,7 @@ impl<T: Clone, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
}

#[cfg(not(no_global_oom_handling))]
impl<T: Copy, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
impl<T: TrivialClone, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
let dst = self.len();
let count = src.end - src.start;
Expand Down
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
#![feature(std_internals)]
#![feature(str_internals)]
#![feature(temporary_niche_types)]
#![feature(trivial_clone)]
#![feature(trusted_fused)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
Expand Down
11 changes: 7 additions & 4 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,9 @@

use core::any::Any;
use core::cell::{Cell, CloneFromCell};
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::clone::UseCloned;
#[cfg(not(no_global_oom_handling))]
use core::clone::{CloneToUninit, TrivialClone};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
Expand Down Expand Up @@ -2224,7 +2224,8 @@ impl<T> Rc<[T]> {

/// Copy elements from slice into newly allocated `Rc<[T]>`
///
/// Unsafe because the caller must either take ownership or bind `T: Copy`
/// Unsafe because the caller must either take ownership, bind `T: Copy` or
/// bind `T: TrivialClone`.
#[cfg(not(no_global_oom_handling))]
unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
unsafe {
Expand Down Expand Up @@ -2314,9 +2315,11 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
}

#[cfg(not(no_global_oom_handling))]
impl<T: Copy> RcFromSlice<T> for Rc<[T]> {
impl<T: TrivialClone> RcFromSlice<T> for Rc<[T]> {
#[inline]
fn from_slice(v: &[T]) -> Self {
// SAFETY: `T` implements `TrivialClone`, so this is sound and equivalent
// to the above.
unsafe { Rc::copy_from_slice(v) }
}
}
Expand Down
Loading
Loading