@@ -10,6 +10,7 @@ use rustc::traits::{
10
10
Environment ,
11
11
} ;
12
12
use rustc:: ty;
13
+ use rustc:: ty:: subst:: { Substs , Subst } ;
13
14
use rustc:: hir;
14
15
use rustc:: hir:: def_id:: DefId ;
15
16
use rustc_target:: spec:: abi;
@@ -48,6 +49,126 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
48
49
} ) ;
49
50
}
50
51
52
+ fn assemble_builtin_sized_impls < ' tcx > (
53
+ tcx : ty:: TyCtxt < ' _ , ' _ , ' tcx > ,
54
+ sized_def_id : DefId ,
55
+ ty : ty:: Ty < ' tcx > ,
56
+ clauses : & mut Vec < Clause < ' tcx > >
57
+ ) {
58
+ let mut push_builtin_impl = |ty : ty:: Ty < ' tcx > , nested : & [ ty:: Ty < ' tcx > ] | {
59
+ let clause = ProgramClause {
60
+ goal : ty:: TraitPredicate {
61
+ trait_ref : ty:: TraitRef {
62
+ def_id : sized_def_id,
63
+ substs : tcx. mk_substs_trait ( ty, & [ ] ) ,
64
+ } ,
65
+ } . lower ( ) ,
66
+ hypotheses : tcx. mk_goals (
67
+ nested. iter ( )
68
+ . cloned ( )
69
+ . map ( |nested_ty| ty:: TraitRef {
70
+ def_id : sized_def_id,
71
+ substs : tcx. mk_substs_trait ( nested_ty, & [ ] ) ,
72
+ } )
73
+ . map ( |trait_ref| ty:: TraitPredicate { trait_ref } )
74
+ . map ( |pred| GoalKind :: DomainGoal ( pred. lower ( ) ) )
75
+ . map ( |goal_kind| tcx. mk_goal ( goal_kind) )
76
+ ) ,
77
+ category : ProgramClauseCategory :: Other ,
78
+ } ;
79
+ // Bind innermost bound vars that may exist in `ty` and `nested`.
80
+ clauses. push ( Clause :: ForAll ( ty:: Binder :: bind ( clause) ) ) ;
81
+ } ;
82
+
83
+ match & ty. sty {
84
+ // Non parametric primitive types.
85
+ ty:: Bool |
86
+ ty:: Char |
87
+ ty:: Int ( ..) |
88
+ ty:: Uint ( ..) |
89
+ ty:: Float ( ..) |
90
+ ty:: Error |
91
+ ty:: Never => push_builtin_impl ( ty, & [ ] ) ,
92
+
93
+ // These ones are always `Sized`.
94
+ & ty:: Array ( _, length) => {
95
+ push_builtin_impl ( tcx. mk_ty ( ty:: Array ( generic_types:: bound ( tcx, 0 ) , length) ) , & [ ] ) ;
96
+ }
97
+ ty:: RawPtr ( ptr) => {
98
+ push_builtin_impl ( generic_types:: raw_ptr ( tcx, ptr. mutbl ) , & [ ] ) ;
99
+ }
100
+ & ty:: Ref ( _, _, mutbl) => {
101
+ push_builtin_impl ( generic_types:: ref_ty ( tcx, mutbl) , & [ ] ) ;
102
+ }
103
+ ty:: FnPtr ( fn_ptr) => {
104
+ let fn_ptr = fn_ptr. skip_binder ( ) ;
105
+ let fn_ptr = generic_types:: fn_ptr (
106
+ tcx,
107
+ fn_ptr. inputs_and_output . len ( ) ,
108
+ fn_ptr. variadic ,
109
+ fn_ptr. unsafety ,
110
+ fn_ptr. abi
111
+ ) ;
112
+ push_builtin_impl ( fn_ptr, & [ ] ) ;
113
+ }
114
+ & ty:: FnDef ( def_id, ..) => {
115
+ push_builtin_impl ( generic_types:: fn_def ( tcx, def_id) , & [ ] ) ;
116
+ }
117
+ & ty:: Closure ( def_id, ..) => {
118
+ push_builtin_impl ( generic_types:: closure ( tcx, def_id) , & [ ] ) ;
119
+ }
120
+ & ty:: Generator ( def_id, ..) => {
121
+ push_builtin_impl ( generic_types:: generator ( tcx, def_id) , & [ ] ) ;
122
+ }
123
+
124
+ // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
125
+ & ty:: Tuple ( type_list) => {
126
+ let type_list = generic_types:: type_list ( tcx, type_list. len ( ) ) ;
127
+ push_builtin_impl ( tcx. mk_ty ( ty:: Tuple ( type_list) ) , & * * type_list) ;
128
+ }
129
+
130
+ // Struct def
131
+ ty:: Adt ( adt_def, _) => {
132
+ let substs = Substs :: bound_vars_for_item ( tcx, adt_def. did ) ;
133
+ let adt = tcx. mk_ty ( ty:: Adt ( adt_def, substs) ) ;
134
+ let sized_constraint = adt_def. sized_constraint ( tcx)
135
+ . iter ( )
136
+ . map ( |ty| ty. subst ( tcx, substs) )
137
+ . collect :: < Vec < _ > > ( ) ;
138
+ push_builtin_impl ( adt, & sized_constraint) ;
139
+ }
140
+
141
+ // Artificially trigger an ambiguity.
142
+ ty:: Infer ( ..) => {
143
+ // Everybody can find at least two types to unify against:
144
+ // general ty vars, int vars and float vars.
145
+ push_builtin_impl ( tcx. types . i32 , & [ ] ) ;
146
+ push_builtin_impl ( tcx. types . u32 , & [ ] ) ;
147
+ push_builtin_impl ( tcx. types . f32 , & [ ] ) ;
148
+ push_builtin_impl ( tcx. types . f64 , & [ ] ) ;
149
+ }
150
+
151
+ ty:: Projection ( _projection_ty) => {
152
+ // FIXME: add builtin impls from the associated type values found in
153
+ // trait impls of `projection_ty.trait_ref(tcx)`.
154
+ }
155
+
156
+ // The `Sized` bound can only come from the environment.
157
+ ty:: Param ( ..) |
158
+ ty:: Placeholder ( ..) |
159
+ ty:: UnnormalizedProjection ( ..) => ( ) ,
160
+
161
+ // Definitely not `Sized`.
162
+ ty:: Foreign ( ..) |
163
+ ty:: Str |
164
+ ty:: Slice ( ..) |
165
+ ty:: Dynamic ( ..) |
166
+ ty:: Opaque ( ..) => ( ) ,
167
+
168
+ ty:: Bound ( ..) |
169
+ ty:: GeneratorWitness ( ..) => bug ! ( "unexpected type {:?}" , ty) ,
170
+ }
171
+ }
51
172
52
173
fn wf_clause_for_raw_ptr < ' tcx > (
53
174
tcx : ty:: TyCtxt < ' _ , ' _ , ' tcx > ,
@@ -236,12 +357,22 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
236
357
// * the trait decl (rule `Implemented-From-Env`)
237
358
238
359
let mut clauses = vec ! [ ] ;
360
+
239
361
assemble_clauses_from_impls (
240
362
self . infcx . tcx ,
241
363
trait_predicate. def_id ( ) ,
242
364
& mut clauses
243
365
) ;
244
366
367
+ if Some ( trait_predicate. def_id ( ) ) == self . infcx . tcx . lang_items ( ) . sized_trait ( ) {
368
+ assemble_builtin_sized_impls (
369
+ self . infcx . tcx ,
370
+ trait_predicate. def_id ( ) ,
371
+ trait_predicate. self_ty ( ) ,
372
+ & mut clauses
373
+ ) ;
374
+ }
375
+
245
376
// FIXME: we need to add special rules for builtin impls:
246
377
// * `Copy` / `Clone`
247
378
// * `Sized`
0 commit comments