Skip to content

Commit 942711e

Browse files
committed
Auto merge of rust-lang#43690 - scalexm:issue-28229, r=nikomatsakis
Generate builtin impls for `Clone` This fixes a long-standing ICE and limitation where some builtin types implement `Copy` but not `Clone` (whereas `Clone` is a super trait of `Copy`). However, this PR has a few side-effects: * `Clone` is now marked as a lang item. * `[T; N]` is now `Clone` if `T: Clone` (currently, only if `T: Copy` and for `N <= 32`). * `fn foo<'a>() where &'a mut (): Clone { }` won't compile anymore because of how bounds for builtin traits are handled (e.g. same thing currently if you replace `Clone` by `Copy` in this example). Of course this function is unusable anyway, an error would pop as soon as it is called. Hence, I'm wondering wether this PR would need an RFC... Also, cc-ing @nikomatsakis, @arielb1. Related issues: rust-lang#28229, rust-lang#24000.
2 parents 8df670b + d58b40e commit 942711e

File tree

18 files changed

+618
-24
lines changed

18 files changed

+618
-24
lines changed

src/libcore/array.rs

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ macro_rules! array_impls {
124124
}
125125

126126
#[stable(feature = "rust1", since = "1.0.0")]
127+
#[cfg(stage0)]
127128
impl<T:Copy> Clone for [T; $N] {
128129
fn clone(&self) -> [T; $N] {
129130
*self

src/libcore/clone.rs

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
/// }
8989
/// ```
9090
#[stable(feature = "rust1", since = "1.0.0")]
91+
#[cfg_attr(not(stage0), lang = "clone")]
9192
pub trait Clone : Sized {
9293
/// Returns a copy of the value.
9394
///
@@ -131,6 +132,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData
131132
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
132133

133134
#[stable(feature = "rust1", since = "1.0.0")]
135+
#[cfg(stage0)]
134136
impl<'a, T: ?Sized> Clone for &'a T {
135137
/// Returns a shallow copy of the reference.
136138
#[inline]
@@ -140,6 +142,7 @@ impl<'a, T: ?Sized> Clone for &'a T {
140142
macro_rules! clone_impl {
141143
($t:ty) => {
142144
#[stable(feature = "rust1", since = "1.0.0")]
145+
#[cfg(stage0)]
143146
impl Clone for $t {
144147
/// Returns a deep copy of the value.
145148
#[inline]

src/libcore/ptr.rs

+3
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
876876
}
877877

878878
#[stable(feature = "rust1", since = "1.0.0")]
879+
#[cfg(stage0)]
879880
impl<T: ?Sized> Clone for *const T {
880881
#[inline]
881882
fn clone(&self) -> *const T {
@@ -884,6 +885,7 @@ impl<T: ?Sized> Clone for *const T {
884885
}
885886

886887
#[stable(feature = "rust1", since = "1.0.0")]
888+
#[cfg(stage0)]
887889
impl<T: ?Sized> Clone for *mut T {
888890
#[inline]
889891
fn clone(&self) -> *mut T {
@@ -895,6 +897,7 @@ impl<T: ?Sized> Clone for *mut T {
895897
macro_rules! fnptr_impls_safety_abi {
896898
($FnTy: ty, $($Arg: ident),*) => {
897899
#[stable(feature = "rust1", since = "1.0.0")]
900+
#[cfg(stage0)]
898901
impl<Ret, $($Arg),*> Clone for $FnTy {
899902
#[inline]
900903
fn clone(&self) -> Self {

src/libcore/tuple.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ macro_rules! tuple_impls {
2222
)+) => {
2323
$(
2424
#[stable(feature = "rust1", since = "1.0.0")]
25+
#[cfg(stage0)]
2526
impl<$($T:Clone),+> Clone for ($($T,)+) {
2627
fn clone(&self) -> ($($T,)+) {
2728
($(self.$idx.clone(),)+)

src/librustc/ich/impls_ty.rs

+4
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::In
663663
def_id.hash_stable(hcx, hasher);
664664
t.hash_stable(hcx, hasher);
665665
}
666+
ty::InstanceDef::CloneShim(def_id, t) => {
667+
def_id.hash_stable(hcx, hasher);
668+
t.hash_stable(hcx, hasher);
669+
}
666670
}
667671
}
668672
}

src/librustc/middle/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ language_item_table! {
274274
SizedTraitLangItem, "sized", sized_trait;
275275
UnsizeTraitLangItem, "unsize", unsize_trait;
276276
CopyTraitLangItem, "copy", copy_trait;
277+
CloneTraitLangItem, "clone", clone_trait;
277278
SyncTraitLangItem, "sync", sync_trait;
278279
FreezeTraitLangItem, "freeze", freeze_trait;
279280

src/librustc/traits/select.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12961296
} else if self.tcx().lang_items.unsize_trait() == Some(def_id) {
12971297
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
12981298
} else {
1299+
if self.tcx().lang_items.clone_trait() == Some(def_id) {
1300+
// Same builtin conditions as `Copy`, i.e. every type which has builtin support
1301+
// for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone`
1302+
// types have builtin support for `Clone`.
1303+
let clone_conditions = self.copy_conditions(obligation);
1304+
self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
1305+
}
1306+
12991307
self.assemble_closure_candidates(obligation, &mut candidates)?;
13001308
self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
13011309
self.assemble_candidates_from_impls(obligation, &mut candidates)?;
@@ -2164,8 +2172,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
21642172

21652173
match candidate {
21662174
BuiltinCandidate { has_nested } => {
2167-
Ok(VtableBuiltin(
2168-
self.confirm_builtin_candidate(obligation, has_nested)))
2175+
let data = self.confirm_builtin_candidate(obligation, has_nested);
2176+
Ok(VtableBuiltin(data))
21692177
}
21702178

21712179
ParamCandidate(param) => {
@@ -2271,6 +2279,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
22712279
_ if Some(trait_def) == self.tcx().lang_items.copy_trait() => {
22722280
self.copy_conditions(obligation)
22732281
}
2282+
_ if Some(trait_def) == self.tcx().lang_items.clone_trait() => {
2283+
self.copy_conditions(obligation)
2284+
}
22742285
_ => bug!("unexpected builtin trait {:?}", trait_def)
22752286
};
22762287
let nested = match conditions {
@@ -2291,6 +2302,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
22912302

22922303
debug!("confirm_builtin_candidate: obligations={:?}",
22932304
obligations);
2305+
22942306
VtableBuiltinData { nested: obligations }
22952307
}
22962308

@@ -2598,8 +2610,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
25982610

25992611
fn confirm_builtin_unsize_candidate(&mut self,
26002612
obligation: &TraitObligation<'tcx>,)
2601-
-> Result<VtableBuiltinData<PredicateObligation<'tcx>>,
2602-
SelectionError<'tcx>> {
2613+
-> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>>
2614+
{
26032615
let tcx = self.tcx();
26042616

26052617
// assemble_candidates_for_unsizing should ensure there are no late bound

src/librustc/traits/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
300300
})
301301
}
302302
traits::VtableParam(n) => Some(traits::VtableParam(n)),
303-
traits::VtableBuiltin(d) => Some(traits::VtableBuiltin(d)),
303+
traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
304304
traits::VtableObject(traits::VtableObjectData {
305305
upcast_trait_ref,
306306
vtable_base,

src/librustc/ty/instance.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,22 @@ pub struct Instance<'tcx> {
2424
pub enum InstanceDef<'tcx> {
2525
Item(DefId),
2626
Intrinsic(DefId),
27-
// <fn() as FnTrait>::call_*
28-
// def-id is FnTrait::call_*
27+
28+
/// <fn() as FnTrait>::call_*
29+
/// def-id is FnTrait::call_*
2930
FnPtrShim(DefId, Ty<'tcx>),
30-
// <Trait as Trait>::fn
31+
32+
/// <Trait as Trait>::fn
3133
Virtual(DefId, usize),
32-
// <[mut closure] as FnOnce>::call_once
34+
35+
/// <[mut closure] as FnOnce>::call_once
3336
ClosureOnceShim { call_once: DefId },
34-
// drop_in_place::<T>; None for empty drop glue.
37+
38+
/// drop_in_place::<T>; None for empty drop glue.
3539
DropGlue(DefId, Option<Ty<'tcx>>),
40+
41+
/// Builtin method implementation, e.g. `Clone::clone`.
42+
CloneShim(DefId, Ty<'tcx>),
3643
}
3744

3845
impl<'tcx> InstanceDef<'tcx> {
@@ -43,9 +50,9 @@ impl<'tcx> InstanceDef<'tcx> {
4350
InstanceDef::FnPtrShim(def_id, _) |
4451
InstanceDef::Virtual(def_id, _) |
4552
InstanceDef::Intrinsic(def_id, ) |
46-
InstanceDef::ClosureOnceShim { call_once: def_id }
47-
=> def_id,
48-
InstanceDef::DropGlue(def_id, _) => def_id
53+
InstanceDef::ClosureOnceShim { call_once: def_id } |
54+
InstanceDef::DropGlue(def_id, _) |
55+
InstanceDef::CloneShim(def_id, _) => def_id
4956
}
5057
}
5158

@@ -80,6 +87,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
8087
InstanceDef::DropGlue(_, ty) => {
8188
write!(f, " - shim({:?})", ty)
8289
}
90+
InstanceDef::CloneShim(_, ty) => {
91+
write!(f, " - shim({:?})", ty)
92+
}
8393
}
8494
}
8595
}

src/librustc/ty/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2232,7 +2232,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
22322232
ty::InstanceDef::FnPtrShim(..) |
22332233
ty::InstanceDef::Virtual(..) |
22342234
ty::InstanceDef::ClosureOnceShim { .. } |
2235-
ty::InstanceDef::DropGlue(..) => {
2235+
ty::InstanceDef::DropGlue(..) |
2236+
ty::InstanceDef::CloneShim(..) => {
22362237
self.mir_shims(instance)
22372238
}
22382239
}

0 commit comments

Comments
 (0)