From 7c430e7646358adae6ff7212074125845ae01010 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 17 Mar 2025 13:11:41 +0100 Subject: [PATCH] automatically implement `TrivialClone` for closures and tuples If each of the component types is `TrivialClone`, the closure/tuple itself can be trivially cloned. --- compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_middle/src/ty/context.rs | 1 + .../src/solve/assembly/mod.rs | 8 +++++--- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 4 +++- compiler/rustc_type_ir/src/lang_items.rs | 1 + library/core/src/clone.rs | 1 + .../ui/functions-closures/trivial-clone-closure.rs | 13 +++++++++++++ 9 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 tests/ui/functions-closures/trivial-clone-closure.rs diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index e454ed58699c..20bf742e7fc7 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -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. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ae83e98f37d2..d7c161a6a609 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -856,6 +856,7 @@ bidirectional_lang_item_map! { PointeeTrait, Sized, TransmuteTrait, + TrivialClone, Tuple, Unpin, Unsize, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 221593d6eadb..57c36a0030aa 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -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) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 44fc6c09677e..49fb6b492d1a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2271,6 +2271,7 @@ symbols! { transparent_enums, transparent_unions, trivial_bounds, + trivial_clone, truncf16, truncf32, truncf64, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cecb43e537a8..d0833f030835 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 88f512708ff0..20a8842f2e8e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -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![]) diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index 5f503d8b912e..39b575ebab63 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -48,6 +48,7 @@ pub enum SolverTraitLangItem { PointeeTrait, Sized, TransmuteTrait, + TrivialClone, Tuple, Unpin, Unsize, diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index eeb26043b39b..40ab760f3e70 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -269,6 +269,7 @@ pub const trait Clone: Sized { issue = "none" )] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] +#[lang = "trivial_clone"] // SAFETY: // It is sound to specialize on this because the `clone` implementation cannot be // lifetime-dependent. Therefore, if `TrivialClone` is implemented for any lifetime, diff --git a/tests/ui/functions-closures/trivial-clone-closure.rs b/tests/ui/functions-closures/trivial-clone-closure.rs new file mode 100644 index 000000000000..5f45d500543a --- /dev/null +++ b/tests/ui/functions-closures/trivial-clone-closure.rs @@ -0,0 +1,13 @@ +//@ run-pass +// Check that closures implement `TrivialClone`. + +#![feature(trivial_clone)] + +use std::clone::TrivialClone; + +fn require_trivial_clone(_t: T) {} + +fn main() { + let some_trivial_clone_value = 42i32; + require_trivial_clone(move || some_trivial_clone_value); +}