@@ -13,12 +13,12 @@ use middle::subst::{FnSpace, SelfSpace};
13
13
use middle:: traits;
14
14
use middle:: traits:: { Obligation , ObligationCause } ;
15
15
use middle:: traits:: report_fulfillment_errors;
16
- use middle:: ty:: { mod, Ty , AsPredicate , ToPolyTraitRef } ;
16
+ use middle:: ty:: { mod, Ty , AsPredicate } ;
17
17
use middle:: infer;
18
- use std:: rc:: Rc ;
19
18
use syntax:: ast;
20
19
use syntax:: codemap:: Span ;
21
- use util:: ppaux:: { Repr , ty_to_string} ;
20
+ use util:: nodemap:: FnvHashSet ;
21
+ use util:: ppaux:: { Repr , UserString } ;
22
22
23
23
pub fn check_object_cast < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
24
24
cast_expr : & ast:: Expr ,
@@ -133,10 +133,33 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
133
133
object_trait : & ty:: TyTrait < ' tcx > ,
134
134
span : Span )
135
135
{
136
+ // Also check that the type `object_trait` specifies all
137
+ // associated types for all supertraits.
138
+ let mut associated_types: FnvHashSet < ( ast:: DefId , ast:: Name ) > = FnvHashSet :: new ( ) ;
139
+
136
140
let object_trait_ref =
137
141
object_trait. principal_trait_ref_with_self_ty ( tcx, tcx. types . err ) ;
138
- for tr in traits:: supertraits ( tcx, object_trait_ref) {
142
+ for tr in traits:: supertraits ( tcx, object_trait_ref. clone ( ) ) {
139
143
check_object_safety_inner ( tcx, & tr, span) ;
144
+
145
+ let trait_def = ty:: lookup_trait_def ( tcx, object_trait_ref. def_id ( ) ) ;
146
+ for & associated_type_name in trait_def. associated_type_names . iter ( ) {
147
+ associated_types. insert ( ( object_trait_ref. def_id ( ) , associated_type_name) ) ;
148
+ }
149
+ }
150
+
151
+ for projection_bound in object_trait. bounds . projection_bounds . iter ( ) {
152
+ let pair = ( projection_bound. 0 . projection_ty . trait_ref . def_id ,
153
+ projection_bound. 0 . projection_ty . item_name ) ;
154
+ associated_types. remove ( & pair) ;
155
+ }
156
+
157
+ for ( trait_def_id, name) in associated_types. into_iter ( ) {
158
+ tcx. sess . span_err (
159
+ span,
160
+ format ! ( "the value of the associated type `{}` (from the trait `{}`) must be specified" ,
161
+ name. user_string( tcx) ,
162
+ ty:: item_path_str( tcx, trait_def_id) ) . as_slice ( ) ) ;
140
163
}
141
164
}
142
165
@@ -201,7 +224,7 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
201
224
Some ( format ! (
202
225
"cannot call a method (`{}`) whose type contains \
203
226
a self-type (`{}`) through a trait object",
204
- method_name, ty_to_string ( tcx, ty ) ) )
227
+ method_name, ty . user_string ( tcx) ) )
205
228
} else {
206
229
None
207
230
}
@@ -343,15 +366,15 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
343
366
referent_ty. repr( fcx. tcx( ) ) ,
344
367
object_trait_ty. repr( fcx. tcx( ) ) ) ;
345
368
369
+ let cause = ObligationCause :: new ( span,
370
+ fcx. body_id ,
371
+ traits:: ObjectCastObligation ( object_trait_ty) ) ;
372
+
346
373
// Create the obligation for casting from T to Trait.
347
374
let object_trait_ref =
348
375
object_trait. principal_trait_ref_with_self_ty ( fcx. tcx ( ) , referent_ty) ;
349
376
let object_obligation =
350
- Obligation :: new (
351
- ObligationCause :: new ( span,
352
- fcx. body_id ,
353
- traits:: ObjectCastObligation ( object_trait_ty) ) ,
354
- object_trait_ref. as_predicate ( ) ) ;
377
+ Obligation :: new ( cause. clone ( ) , object_trait_ref. as_predicate ( ) ) ;
355
378
fcx. register_predicate ( object_obligation) ;
356
379
357
380
// Create additional obligations for all the various builtin
@@ -362,7 +385,15 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
362
385
fcx. register_builtin_bound (
363
386
referent_ty,
364
387
builtin_bound,
365
- ObligationCause :: new ( span, fcx. body_id , traits:: ObjectCastObligation ( object_trait_ty) ) ) ;
388
+ cause. clone ( ) ) ;
389
+ }
390
+
391
+ // Finally, create obligations for the projection predicates.
392
+ let projection_bounds = object_trait. projection_bounds_with_self_ty ( referent_ty) ;
393
+ for projection_bound in projection_bounds. iter ( ) {
394
+ let projection_obligation =
395
+ Obligation :: new ( cause. clone ( ) , projection_bound. as_predicate ( ) ) ;
396
+ fcx. register_predicate ( projection_obligation) ;
366
397
}
367
398
368
399
object_trait_ref
0 commit comments