automatically implement TrivialClone for closures and tuples

If each of the component types is `TrivialClone`, the closure/tuple itself can be trivially cloned.
This commit is contained in:
joboet 2025-03-17 13:11:41 +01:00
parent 7b72cc6156
commit 7c430e7646
No known key found for this signature in database
GPG key ID: 704E0149B0194B3C
9 changed files with 27 additions and 5 deletions

View file

@ -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.

View file

@ -856,6 +856,7 @@ bidirectional_lang_item_map! {
PointeeTrait,
Sized,
TransmuteTrait,
TrivialClone,
Tuple,
Unpin,
Unsize,

View file

@ -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)
}

View file

@ -2271,6 +2271,7 @@ symbols! {
transparent_enums,
transparent_unions,
trivial_bounds,
trivial_clone,
truncf16,
truncf32,
truncf64,

View file

@ -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

View file

@ -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![])

View file

@ -48,6 +48,7 @@ pub enum SolverTraitLangItem {
PointeeTrait,
Sized,
TransmuteTrait,
TrivialClone,
Tuple,
Unpin,
Unsize,

View file

@ -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,

View file

@ -0,0 +1,13 @@
//@ run-pass
// Check that closures implement `TrivialClone`.
#![feature(trivial_clone)]
use std::clone::TrivialClone;
fn require_trivial_clone<T: TrivialClone>(_t: T) {}
fn main() {
let some_trivial_clone_value = 42i32;
require_trivial_clone(move || some_trivial_clone_value);
}