@@ -10,6 +10,7 @@ use rustc::traits::{
1010 Environment ,
1111} ;
1212use rustc:: ty;
13+ use rustc:: ty:: subst:: { Substs , Subst } ;
1314use rustc:: hir;
1415use rustc:: hir:: def_id:: DefId ;
1516use rustc_target:: spec:: abi;
@@ -48,6 +49,126 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
4849 } ) ;
4950}
5051
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+ }
51172
52173fn wf_clause_for_raw_ptr < ' tcx > (
53174 tcx : ty:: TyCtxt < ' _ , ' _ , ' tcx > ,
@@ -236,12 +357,22 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
236357 // * the trait decl (rule `Implemented-From-Env`)
237358
238359 let mut clauses = vec ! [ ] ;
360+
239361 assemble_clauses_from_impls (
240362 self . infcx . tcx ,
241363 trait_predicate. def_id ( ) ,
242364 & mut clauses
243365 ) ;
244366
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+
245376 // FIXME: we need to add special rules for builtin impls:
246377 // * `Copy` / `Clone`
247378 // * `Sized`
0 commit comments