Skip to content

Commit 5e5e944

Browse files
committed
Only generate a single shim for clone of copy types.
1 parent c2354aa commit 5e5e944

File tree

15 files changed

+50
-29
lines changed

15 files changed

+50
-29
lines changed

compiler/rustc_const_eval/src/interpret/terminator.rs

+1
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
544544
| ty::InstanceDef::FnPtrShim(..)
545545
| ty::InstanceDef::DropGlue(..)
546546
| ty::InstanceDef::CloneShim(..)
547+
| ty::InstanceDef::CloneCopyShim(..)
547548
| ty::InstanceDef::FnPtrAddrShim(..)
548549
| ty::InstanceDef::ThreadLocalShim(..)
549550
| ty::InstanceDef::Item(_) => {

compiler/rustc_middle/src/mir/mono.rs

+1
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ impl<'tcx> CodegenUnit<'tcx> {
404404
| InstanceDef::ClosureOnceShim { .. }
405405
| InstanceDef::DropGlue(..)
406406
| InstanceDef::CloneShim(..)
407+
| InstanceDef::CloneCopyShim(..)
407408
| InstanceDef::ThreadLocalShim(..)
408409
| InstanceDef::FnPtrAddrShim(..) => None,
409410
}

compiler/rustc_middle/src/mir/visit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ macro_rules! make_mir_visitor {
344344
ty::InstanceDef::ReifyShim(_def_id) |
345345
ty::InstanceDef::Virtual(_def_id, _) |
346346
ty::InstanceDef::ThreadLocalShim(_def_id) |
347+
ty::InstanceDef::CloneCopyShim(_def_id) |
347348
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
348349
ty::InstanceDef::DropGlue(_def_id, None) => {}
349350

compiler/rustc_middle/src/ty/instance.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,13 @@ pub enum InstanceDef<'tcx> {
9797
/// glue.
9898
DropGlue(DefId, Option<Ty<'tcx>>),
9999

100+
/// Compiler-generated `<T as Clone>::clone` implementation where T is `Copy`.
101+
///
102+
/// The `DefId` is for `Clone::clone`.
103+
CloneCopyShim(DefId),
104+
100105
/// Compiler-generated `<T as Clone>::clone` implementation.
101106
///
102-
/// For all types that automatically implement `Copy`, a trivial `Clone` impl is provided too.
103107
/// Additionally, arrays, tuples, and closures get a `Clone` shim even if they aren't `Copy`.
104108
///
105109
/// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl.
@@ -168,6 +172,7 @@ impl<'tcx> InstanceDef<'tcx> {
168172
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
169173
| InstanceDef::DropGlue(def_id, _)
170174
| InstanceDef::CloneShim(def_id, _)
175+
| InstanceDef::CloneCopyShim(def_id)
171176
| InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
172177
}
173178
}
@@ -187,6 +192,7 @@ impl<'tcx> InstanceDef<'tcx> {
187192
| InstanceDef::ClosureOnceShim { .. }
188193
| InstanceDef::DropGlue(..)
189194
| InstanceDef::CloneShim(..)
195+
| InstanceDef::CloneCopyShim(..)
190196
| InstanceDef::FnPtrAddrShim(..) => None,
191197
}
192198
}
@@ -280,6 +286,7 @@ impl<'tcx> InstanceDef<'tcx> {
280286
| InstanceDef::FnPtrShim(..)
281287
| InstanceDef::DropGlue(_, Some(_)) => false,
282288
InstanceDef::ClosureOnceShim { .. }
289+
| InstanceDef::CloneCopyShim(..)
283290
| InstanceDef::DropGlue(..)
284291
| InstanceDef::Item(_)
285292
| InstanceDef::Intrinsic(..)
@@ -316,6 +323,7 @@ fn fmt_instance(
316323
InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"),
317324
InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
318325
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"),
326+
InstanceDef::CloneCopyShim(_) => write!(f, " - shim(<Copy>)"),
319327
InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
320328
}
321329
}

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,7 @@ impl<'tcx> TyCtxt<'tcx> {
23312331
| ty::InstanceDef::ClosureOnceShim { .. }
23322332
| ty::InstanceDef::DropGlue(..)
23332333
| ty::InstanceDef::CloneShim(..)
2334+
| ty::InstanceDef::CloneCopyShim(..)
23342335
| ty::InstanceDef::ThreadLocalShim(..)
23352336
| ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance),
23362337
}

compiler/rustc_mir_transform/src/inline.rs

+1
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ impl<'tcx> Inliner<'tcx> {
319319
| InstanceDef::ClosureOnceShim { .. }
320320
| InstanceDef::DropGlue(..)
321321
| InstanceDef::CloneShim(..)
322+
| InstanceDef::CloneCopyShim(..)
322323
| InstanceDef::ThreadLocalShim(..)
323324
| InstanceDef::FnPtrAddrShim(..) => return Ok(()),
324325
}

compiler/rustc_mir_transform/src/inline/cycle.rs

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
8888
| InstanceDef::FnPtrShim(..)
8989
| InstanceDef::ClosureOnceShim { .. }
9090
| InstanceDef::ThreadLocalShim { .. }
91+
| InstanceDef::CloneCopyShim(..)
9192
| InstanceDef::CloneShim(..) => {}
9293

9394
// This shim does not call any other functions, thus there can be no recursion.

compiler/rustc_mir_transform/src/shim.rs

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
use rustc_hir as hir;
22
use rustc_hir::def_id::DefId;
33
use rustc_hir::lang_items::LangItem;
4+
use rustc_index::{Idx, IndexVec};
45
use rustc_middle::mir::*;
56
use rustc_middle::query::Providers;
67
use rustc_middle::ty::GenericArgs;
78
use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt};
8-
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
9-
10-
use rustc_index::{Idx, IndexVec};
11-
9+
use rustc_span::symbol::kw;
1210
use rustc_span::Span;
11+
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
1312
use rustc_target::spec::abi::Abi;
1413

1514
use std::fmt;
@@ -90,7 +89,18 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
9089
build_drop_shim(tcx, def_id, ty)
9190
}
9291
ty::InstanceDef::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance),
93-
ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
92+
ty::InstanceDef::CloneCopyShim(def_id) => {
93+
let self_ty = Ty::new_param(tcx, 0, kw::SelfUpper);
94+
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
95+
builder.copy_shim();
96+
let mut result = builder.into_mir(instance);
97+
// Mark as runtime MIR to bypass MIR validation checking `Operand::Copy`.
98+
result.phase = MirPhase::Runtime(RuntimePhase::Initial);
99+
result
100+
}
101+
ty::InstanceDef::CloneShim(def_id, ty) => {
102+
build_clone_shim(tcx, def_id, ty).into_mir(instance)
103+
}
94104
ty::InstanceDef::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty),
95105
ty::InstanceDef::Virtual(..) => {
96106
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
@@ -379,19 +389,18 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t
379389
}
380390

381391
/// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
382-
fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
383-
debug!("build_clone_shim(def_id={:?})", def_id);
384-
385-
let param_env = tcx.param_env_reveal_all_normalized(def_id);
386-
392+
#[instrument(level = "trace", skip(tcx))]
393+
fn build_clone_shim<'tcx>(
394+
tcx: TyCtxt<'tcx>,
395+
def_id: DefId,
396+
self_ty: Ty<'tcx>,
397+
) -> CloneShimBuilder<'tcx> {
387398
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
388-
let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
389399

390400
let dest = Place::return_place();
391401
let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));
392402

393403
match self_ty.kind() {
394-
_ if is_copy => builder.copy_shim(),
395404
ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
396405
ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
397406
ty::Coroutine(coroutine_def_id, args) => {
@@ -401,7 +410,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
401410
_ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty),
402411
};
403412

404-
builder.into_mir()
413+
builder
405414
}
406415

407416
struct CloneShimBuilder<'tcx> {
@@ -432,11 +441,8 @@ impl<'tcx> CloneShimBuilder<'tcx> {
432441
}
433442
}
434443

435-
fn into_mir(self) -> Body<'tcx> {
436-
let source = MirSource::from_instance(ty::InstanceDef::CloneShim(
437-
self.def_id,
438-
self.sig.inputs_and_output[0],
439-
));
444+
fn into_mir(self, def: ty::InstanceDef<'tcx>) -> Body<'tcx> {
445+
let source = MirSource::from_instance(def);
440446
new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
441447
}
442448

compiler/rustc_monomorphize/src/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ fn visit_instance_use<'tcx>(
961961
| ty::InstanceDef::Item(..)
962962
| ty::InstanceDef::FnPtrShim(..)
963963
| ty::InstanceDef::CloneShim(..)
964+
| ty::InstanceDef::CloneCopyShim(..)
964965
| ty::InstanceDef::FnPtrAddrShim(..) => {
965966
output.push(create_fn_mono_item(tcx, instance, source));
966967
}

compiler/rustc_monomorphize/src/partitioning.rs

+2
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
624624
| ty::InstanceDef::DropGlue(..)
625625
| ty::InstanceDef::Virtual(..)
626626
| ty::InstanceDef::CloneShim(..)
627+
| ty::InstanceDef::CloneCopyShim(..)
627628
| ty::InstanceDef::ThreadLocalShim(..)
628629
| ty::InstanceDef::FnPtrAddrShim(..) => return None,
629630
};
@@ -785,6 +786,7 @@ fn mono_item_visibility<'tcx>(
785786
| InstanceDef::ClosureOnceShim { .. }
786787
| InstanceDef::DropGlue(..)
787788
| InstanceDef::CloneShim(..)
789+
| InstanceDef::CloneCopyShim(..)
788790
| InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden,
789791
};
790792

compiler/rustc_smir/src/rustc_smir/convert/ty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
799799
| ty::InstanceDef::ThreadLocalShim(..)
800800
| ty::InstanceDef::DropGlue(..)
801801
| ty::InstanceDef::CloneShim(..)
802+
| ty::InstanceDef::CloneCopyShim(..)
802803
| ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim,
803804
};
804805
stable_mir::mir::mono::Instance { def, kind }

compiler/rustc_ty_utils/src/instance.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -210,19 +210,16 @@ fn resolve_associated_item<'tcx>(
210210
let self_ty = trait_ref.self_ty();
211211

212212
let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
213-
match self_ty.kind() {
214-
_ if is_copy => (),
213+
let def = match self_ty.kind() {
214+
_ if is_copy => ty::InstanceDef::CloneCopyShim(trait_item_id),
215215
ty::Coroutine(..)
216216
| ty::CoroutineWitness(..)
217217
| ty::Closure(..)
218-
| ty::Tuple(..) => {}
218+
| ty::Tuple(..) => ty::InstanceDef::CloneShim(trait_item_id, self_ty),
219219
_ => return Ok(None),
220220
};
221221

222-
Some(Instance {
223-
def: ty::InstanceDef::CloneShim(trait_item_id, self_ty),
224-
args: rcvr_args,
225-
})
222+
Some(Instance { def, args: rcvr_args })
226223
} else {
227224
assert_eq!(name, sym::clone_from);
228225

tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
debug f => _1;
66
let mut _0: fn(A, B);
77
let mut _2: &fn(A, B);
8-
+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) {
8+
+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(<Copy>)) {
99
+ }
1010

1111
bb0: {

tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
debug f => _1;
66
let mut _0: fn(A, B);
77
let mut _2: &fn(A, B);
8-
+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) {
8+
+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(<Copy>)) {
99
+ }
1010

1111
bb0: {

tests/mir-opt/inline/inline_shims.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// EMIT_MIR inline_shims.clone.Inline.diff
55
pub fn clone<A, B>(f: fn(A, B)) -> fn(A, B) {
66
// CHECK-LABEL: fn clone(
7-
// CHECK: (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B)))
7+
// CHECK: (inlined <fn(A, B) as Clone>::clone - shim(<Copy>))
88
f.clone()
99
}
1010

0 commit comments

Comments
 (0)