1212use middle:: freevars:: freevar_entry;
1313use middle:: freevars;
1414use middle:: subst;
15+ use middle:: ty:: ParameterEnvironment ;
1516use middle:: ty;
16- use middle:: ty_fold;
1717use middle:: ty_fold:: TypeFoldable ;
18- use middle:: typeck;
18+ use middle:: ty_fold;
19+ use middle:: typeck:: check:: vtable;
1920use middle:: typeck:: { MethodCall , NoAdjustment } ;
21+ use middle:: typeck;
2022use util:: ppaux:: { Repr , ty_to_string} ;
2123use util:: ppaux:: UserString ;
2224
25+ use std:: collections:: HashSet ;
2326use syntax:: ast:: * ;
27+ use syntax:: ast_util;
2428use syntax:: attr;
2529use syntax:: codemap:: Span ;
2630use syntax:: print:: pprust:: { expr_to_string, ident_to_string} ;
27- use syntax:: { visit} ;
2831use syntax:: visit:: Visitor ;
32+ use syntax:: visit;
2933
3034// Kind analysis pass.
3135//
@@ -47,13 +51,13 @@ use syntax::visit::Visitor;
4751// primitives in the stdlib are explicitly annotated to only take sendable
4852// types.
4953
50- #[ deriving( Clone ) ]
5154pub struct Context < ' a > {
5255 tcx : & ' a ty:: ctxt ,
56+ struct_and_enum_bounds_checked : HashSet < ty:: t > ,
57+ parameter_environments : Vec < ParameterEnvironment > ,
5358}
5459
5560impl < ' a > Visitor < ( ) > for Context < ' a > {
56-
5761 fn visit_expr ( & mut self , ex : & Expr , _: ( ) ) {
5862 check_expr ( self , ex) ;
5963 }
@@ -74,12 +78,18 @@ impl<'a> Visitor<()> for Context<'a> {
7478 fn visit_pat ( & mut self , p : & Pat , _: ( ) ) {
7579 check_pat ( self , p) ;
7680 }
81+
82+ fn visit_local ( & mut self , l : & Local , _: ( ) ) {
83+ check_local ( self , l) ;
84+ }
7785}
7886
7987pub fn check_crate ( tcx : & ty:: ctxt ,
8088 krate : & Crate ) {
8189 let mut ctx = Context {
8290 tcx : tcx,
91+ struct_and_enum_bounds_checked : HashSet :: new ( ) ,
92+ parameter_environments : Vec :: new ( ) ,
8393 } ;
8494 visit:: walk_crate ( & mut ctx, krate, ( ) ) ;
8595 tcx. sess . abort_if_errors ( ) ;
@@ -165,12 +175,90 @@ fn check_item(cx: &mut Context, item: &Item) {
165175 match item. node {
166176 ItemImpl ( _, Some ( ref trait_ref) , ref self_type, _) => {
167177 check_impl_of_trait ( cx, item, trait_ref, & * * self_type) ;
178+
179+ let parameter_environment =
180+ ParameterEnvironment :: for_item ( cx. tcx , item. id ) ;
181+ cx. parameter_environments . push ( parameter_environment) ;
182+
183+ // Check bounds on the `self` type.
184+ check_bounds_on_structs_or_enums_in_type_if_possible (
185+ cx,
186+ item. span ,
187+ ty:: node_id_to_type ( cx. tcx , item. id ) ) ;
188+
189+ // Check bounds on the trait ref.
190+ match ty:: impl_trait_ref ( cx. tcx ,
191+ ast_util:: local_def ( item. id ) ) {
192+ None => { }
193+ Some ( trait_ref) => {
194+ check_bounds_on_structs_or_enums_in_trait_ref (
195+ cx,
196+ item. span ,
197+ & * trait_ref) ;
198+ }
199+ }
200+
201+ drop ( cx. parameter_environments . pop ( ) ) ;
202+ }
203+ ItemEnum ( ..) => {
204+ let parameter_environment =
205+ ParameterEnvironment :: for_item ( cx. tcx , item. id ) ;
206+ cx. parameter_environments . push ( parameter_environment) ;
207+
208+ let def_id = ast_util:: local_def ( item. id ) ;
209+ for variant in ty:: enum_variants ( cx. tcx , def_id) . iter ( ) {
210+ for arg in variant. args . iter ( ) {
211+ check_bounds_on_structs_or_enums_in_type_if_possible (
212+ cx,
213+ item. span ,
214+ * arg)
215+ }
216+ }
217+
218+ drop ( cx. parameter_environments . pop ( ) ) ;
219+ }
220+ ItemStruct ( ..) => {
221+ let parameter_environment =
222+ ParameterEnvironment :: for_item ( cx. tcx , item. id ) ;
223+ cx. parameter_environments . push ( parameter_environment) ;
224+
225+ let def_id = ast_util:: local_def ( item. id ) ;
226+ for field in ty:: lookup_struct_fields ( cx. tcx , def_id) . iter ( ) {
227+ check_bounds_on_structs_or_enums_in_type_if_possible (
228+ cx,
229+ item. span ,
230+ ty:: node_id_to_type ( cx. tcx , field. id . node ) )
231+ }
232+
233+ drop ( cx. parameter_environments . pop ( ) ) ;
234+
235+ }
236+ ItemStatic ( ..) => {
237+ let parameter_environment =
238+ ParameterEnvironment :: for_item ( cx. tcx , item. id ) ;
239+ cx. parameter_environments . push ( parameter_environment) ;
240+
241+ check_bounds_on_structs_or_enums_in_type_if_possible (
242+ cx,
243+ item. span ,
244+ ty:: node_id_to_type ( cx. tcx , item. id ) ) ;
245+
246+ drop ( cx. parameter_environments . pop ( ) ) ;
168247 }
169248 _ => { }
170249 }
171250 }
172251
173- visit:: walk_item ( cx, item, ( ) ) ;
252+ visit:: walk_item ( cx, item, ( ) )
253+ }
254+
255+ fn check_local ( cx : & mut Context , local : & Local ) {
256+ check_bounds_on_structs_or_enums_in_type_if_possible (
257+ cx,
258+ local. span ,
259+ ty:: node_id_to_type ( cx. tcx , local. id ) ) ;
260+
261+ visit:: walk_local ( cx, local, ( ) )
174262}
175263
176264// Yields the appropriate function to check the kind of closed over
@@ -254,7 +342,25 @@ fn check_fn(
254342 } ) ;
255343 } ) ;
256344
257- visit:: walk_fn ( cx, fk, decl, body, sp, ( ) ) ;
345+ match * fk {
346+ visit:: FkFnBlock ( ..) => {
347+ let ty = ty:: node_id_to_type ( cx. tcx , fn_id) ;
348+ check_bounds_on_structs_or_enums_in_type_if_possible ( cx, sp, ty) ;
349+
350+ visit:: walk_fn ( cx, fk, decl, body, sp, ( ) )
351+ }
352+ visit:: FkItemFn ( ..) | visit:: FkMethod ( ..) => {
353+ let parameter_environment = ParameterEnvironment :: for_item ( cx. tcx ,
354+ fn_id) ;
355+ cx. parameter_environments . push ( parameter_environment) ;
356+
357+ let ty = ty:: node_id_to_type ( cx. tcx , fn_id) ;
358+ check_bounds_on_structs_or_enums_in_type_if_possible ( cx, sp, ty) ;
359+
360+ visit:: walk_fn ( cx, fk, decl, body, sp, ( ) ) ;
361+ drop ( cx. parameter_environments . pop ( ) ) ;
362+ }
363+ }
258364}
259365
260366pub fn check_expr ( cx : & mut Context , e : & Expr ) {
@@ -263,6 +369,13 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
263369 // Handle any kind bounds on type parameters
264370 check_bounds_on_type_parameters ( cx, e) ;
265371
372+ // Check bounds on structures or enumerations in the type of the
373+ // expression.
374+ let expression_type = ty:: expr_ty ( cx. tcx , e) ;
375+ check_bounds_on_structs_or_enums_in_type_if_possible ( cx,
376+ e. span ,
377+ expression_type) ;
378+
266379 match e. node {
267380 ExprBox ( ref loc, ref interior) => {
268381 let def = ty:: resolve_expr ( cx. tcx , & * * loc) ;
@@ -483,6 +596,7 @@ fn check_ty(cx: &mut Context, aty: &Ty) {
483596 }
484597 _ => { }
485598 }
599+
486600 visit:: walk_ty ( cx, aty, ( ) ) ;
487601}
488602
@@ -519,6 +633,76 @@ pub fn check_typaram_bounds(cx: &Context,
519633 } ) ;
520634}
521635
636+ fn check_bounds_on_structs_or_enums_in_type_if_possible ( cx : & mut Context ,
637+ span : Span ,
638+ ty : ty:: t ) {
639+ // If we aren't in a function, structure, or enumeration context, we don't
640+ // have enough information to ensure that bounds on structures or
641+ // enumerations are satisfied. So we don't perform the check.
642+ if cx. parameter_environments . len ( ) == 0 {
643+ return
644+ }
645+
646+ // If we've already checked for this type, don't do it again. This
647+ // massively speeds up kind checking.
648+ if cx. struct_and_enum_bounds_checked . contains ( & ty) {
649+ return
650+ }
651+ cx. struct_and_enum_bounds_checked . insert ( ty) ;
652+
653+ ty:: walk_ty ( ty, |ty| {
654+ match ty:: get ( ty) . sty {
655+ ty:: ty_struct( type_id, ref substs) |
656+ ty:: ty_enum( type_id, ref substs) => {
657+ let polytype = ty:: lookup_item_type ( cx. tcx , type_id) ;
658+
659+ // Check builtin bounds.
660+ for ( ty, type_param_def) in substs. types
661+ . iter ( )
662+ . zip ( polytype. generics
663+ . types
664+ . iter ( ) ) {
665+ check_typaram_bounds ( cx, span, * ty, type_param_def)
666+ }
667+
668+ // Check trait bounds.
669+ let parameter_environment =
670+ cx. parameter_environments . get ( cx. parameter_environments
671+ . len ( ) - 1 ) ;
672+ debug ! (
673+ "check_bounds_on_structs_or_enums_in_type_if_possible(): \
674+ checking {}",
675+ ty. repr( cx. tcx) ) ;
676+ vtable:: check_param_bounds ( cx. tcx ,
677+ span,
678+ parameter_environment,
679+ & polytype. generics . types ,
680+ substs,
681+ |missing| {
682+ cx. tcx
683+ . sess
684+ . span_err ( span,
685+ format ! ( "instantiating a type parameter with \
686+ an incompatible type `{}`, which \
687+ does not fulfill `{}`",
688+ ty_to_string( cx. tcx, ty) ,
689+ missing. user_string(
690+ cx. tcx) ) . as_slice ( ) ) ;
691+ } )
692+ }
693+ _ => { }
694+ }
695+ } ) ;
696+ }
697+
698+ fn check_bounds_on_structs_or_enums_in_trait_ref ( cx : & mut Context ,
699+ span : Span ,
700+ trait_ref : & ty:: TraitRef ) {
701+ for ty in trait_ref. substs . types . iter ( ) {
702+ check_bounds_on_structs_or_enums_in_type_if_possible ( cx, span, * ty)
703+ }
704+ }
705+
522706pub fn check_freevar_bounds ( cx : & Context , sp : Span , ty : ty:: t ,
523707 bounds : ty:: BuiltinBounds , referenced_ty : Option < ty:: t > )
524708{
0 commit comments