@@ -6,10 +6,42 @@ use rustc::traits::{
66} ;
77use rustc:: ty;
88use rustc:: ty:: subst:: { InternalSubsts , Subst } ;
9+ use rustc:: hir;
910use rustc:: hir:: def_id:: DefId ;
1011use crate :: lowering:: Lower ;
1112use crate :: generic_types;
1213
14+ /// Returns a predicate of the form
15+ /// `Implemented(ty: Trait) :- Implemented(nested: Trait)...`
16+ /// where `Trait` is specified by `trait_def_id`.
17+ fn builtin_impl_clause (
18+ tcx : ty:: TyCtxt < ' _ , ' _ , ' tcx > ,
19+ ty : ty:: Ty < ' tcx > ,
20+ nested : & [ ty:: Ty < ' tcx > ] ,
21+ trait_def_id : DefId
22+ ) -> ProgramClause < ' tcx > {
23+ ProgramClause {
24+ goal : ty:: TraitPredicate {
25+ trait_ref : ty:: TraitRef {
26+ def_id : trait_def_id,
27+ substs : tcx. mk_substs_trait ( ty, & [ ] ) ,
28+ } ,
29+ } . lower ( ) ,
30+ hypotheses : tcx. mk_goals (
31+ nested. iter ( )
32+ . cloned ( )
33+ . map ( |nested_ty| ty:: TraitRef {
34+ def_id : trait_def_id,
35+ substs : tcx. mk_substs_trait ( nested_ty, & [ ] ) ,
36+ } )
37+ . map ( |trait_ref| ty:: TraitPredicate { trait_ref } )
38+ . map ( |pred| GoalKind :: DomainGoal ( pred. lower ( ) ) )
39+ . map ( |goal_kind| tcx. mk_goal ( goal_kind) )
40+ ) ,
41+ category : ProgramClauseCategory :: Other ,
42+ }
43+ }
44+
1345crate fn assemble_builtin_unsize_impls < ' tcx > (
1446 tcx : ty:: TyCtxt < ' _ , ' _ , ' tcx > ,
1547 unsize_def_id : DefId ,
@@ -93,26 +125,7 @@ crate fn assemble_builtin_sized_impls<'tcx>(
93125 clauses : & mut Vec < Clause < ' tcx > >
94126) {
95127 let mut push_builtin_impl = |ty : ty:: Ty < ' tcx > , nested : & [ ty:: Ty < ' tcx > ] | {
96- let clause = ProgramClause {
97- goal : ty:: TraitPredicate {
98- trait_ref : ty:: TraitRef {
99- def_id : sized_def_id,
100- substs : tcx. mk_substs_trait ( ty, & [ ] ) ,
101- } ,
102- } . lower ( ) ,
103- hypotheses : tcx. mk_goals (
104- nested. iter ( )
105- . cloned ( )
106- . map ( |nested_ty| ty:: TraitRef {
107- def_id : sized_def_id,
108- substs : tcx. mk_substs_trait ( nested_ty, & [ ] ) ,
109- } )
110- . map ( |trait_ref| ty:: TraitPredicate { trait_ref } )
111- . map ( |pred| GoalKind :: DomainGoal ( pred. lower ( ) ) )
112- . map ( |goal_kind| tcx. mk_goal ( goal_kind) )
113- ) ,
114- category : ProgramClauseCategory :: Other ,
115- } ;
128+ let clause = builtin_impl_clause ( tcx, ty, nested, sized_def_id) ;
116129 // Bind innermost bound vars that may exist in `ty` and `nested`.
117130 clauses. push ( Clause :: ForAll ( ty:: Binder :: bind ( clause) ) ) ;
118131 } ;
@@ -206,3 +219,99 @@ crate fn assemble_builtin_sized_impls<'tcx>(
206219 ty:: GeneratorWitness ( ..) => bug ! ( "unexpected type {:?}" , ty) ,
207220 }
208221}
222+
223+ crate fn assemble_builtin_copy_clone_impls < ' tcx > (
224+ tcx : ty:: TyCtxt < ' _ , ' _ , ' tcx > ,
225+ trait_def_id : DefId ,
226+ ty : ty:: Ty < ' tcx > ,
227+ clauses : & mut Vec < Clause < ' tcx > >
228+ ) {
229+ let mut push_builtin_impl = |ty : ty:: Ty < ' tcx > , nested : & [ ty:: Ty < ' tcx > ] | {
230+ let clause = builtin_impl_clause ( tcx, ty, nested, trait_def_id) ;
231+ // Bind innermost bound vars that may exist in `ty` and `nested`.
232+ clauses. push ( Clause :: ForAll ( ty:: Binder :: bind ( clause) ) ) ;
233+ } ;
234+
235+ match & ty. sty {
236+ // Implementations provided in libcore.
237+ ty:: Bool |
238+ ty:: Char |
239+ ty:: Int ( ..) |
240+ ty:: Uint ( ..) |
241+ ty:: Float ( ..) |
242+ ty:: RawPtr ( ..) |
243+ ty:: Never |
244+ ty:: Ref ( _, _, hir:: MutImmutable ) => ( ) ,
245+
246+ // Non parametric primitive type.
247+ ty:: Error => push_builtin_impl ( ty, & [ ] ) ,
248+
249+ // These implement `Copy`/`Clone` if their element types do.
250+ & ty:: Array ( _, length) => {
251+ let element_ty = generic_types:: bound ( tcx, 0 ) ;
252+ push_builtin_impl ( tcx. mk_ty ( ty:: Array ( element_ty, length) ) , & [ element_ty] ) ;
253+ }
254+ & ty:: Tuple ( type_list) => {
255+ let type_list = generic_types:: type_list ( tcx, type_list. len ( ) ) ;
256+ push_builtin_impl ( tcx. mk_ty ( ty:: Tuple ( type_list) ) , & * * type_list) ;
257+ }
258+ & ty:: Closure ( def_id, ..) => {
259+ let closure_ty = generic_types:: closure ( tcx, def_id) ;
260+ let upvar_tys: Vec < _ > = match & closure_ty. sty {
261+ ty:: Closure ( _, substs) => substs. upvar_tys ( def_id, tcx) . collect ( ) ,
262+ _ => bug ! ( ) ,
263+ } ;
264+ push_builtin_impl ( closure_ty, & upvar_tys) ;
265+ }
266+
267+ // These ones are always `Clone`.
268+ ty:: FnPtr ( fn_ptr) => {
269+ let fn_ptr = fn_ptr. skip_binder ( ) ;
270+ let fn_ptr = generic_types:: fn_ptr (
271+ tcx,
272+ fn_ptr. inputs_and_output . len ( ) ,
273+ fn_ptr. c_variadic ,
274+ fn_ptr. unsafety ,
275+ fn_ptr. abi
276+ ) ;
277+ push_builtin_impl ( fn_ptr, & [ ] ) ;
278+ }
279+ & ty:: FnDef ( def_id, ..) => {
280+ push_builtin_impl ( generic_types:: fn_def ( tcx, def_id) , & [ ] ) ;
281+ }
282+
283+ // These depend on whatever user-defined impls might exist.
284+ ty:: Adt ( _, _) => ( ) ,
285+
286+ // int vars and float vars are always `Copy`.
287+ // Other vars will trigger an ambiguity.
288+ ty:: Infer ( ..) => {
289+ push_builtin_impl ( tcx. types . i32 , & [ ] ) ;
290+ push_builtin_impl ( tcx. types . u32 , & [ ] ) ;
291+ push_builtin_impl ( tcx. types . f32 , & [ ] ) ;
292+ push_builtin_impl ( tcx. types . f64 , & [ ] ) ;
293+ }
294+
295+ ty:: Projection ( _projection_ty) => {
296+ // FIXME: add builtin impls from the associated type values found in
297+ // trait impls of `projection_ty.trait_ref(tcx)`.
298+ }
299+
300+ // The `Copy`/`Clone` bound can only come from the environment.
301+ ty:: Param ( ..) |
302+ ty:: Placeholder ( ..) |
303+ ty:: UnnormalizedProjection ( ..) |
304+ ty:: Opaque ( ..) => ( ) ,
305+
306+ // Definitely not `Copy`/`Clone`.
307+ ty:: Dynamic ( ..) |
308+ ty:: Foreign ( ..) |
309+ ty:: Generator ( ..) |
310+ ty:: Str |
311+ ty:: Slice ( ..) |
312+ ty:: Ref ( _, _, hir:: MutMutable ) => ( ) ,
313+
314+ ty:: Bound ( ..) |
315+ ty:: GeneratorWitness ( ..) => bug ! ( "unexpected type {:?}" , ty) ,
316+ }
317+ }
0 commit comments