@@ -172,11 +172,13 @@ pub struct Inherited<'a, 'tcx: 'a> {
172
172
173
173
deferred_cast_checks : RefCell < Vec < cast:: CastCheck < ' tcx > > > ,
174
174
175
- // Anonymized types found in explicit return types and their
176
- // associated fresh inference variable. Writeback resolves these
177
- // variables to get the concrete type, which can be used to
178
- // deanonymize TyAnon, after typeck is done with all functions.
179
- anon_types : RefCell < Vec < ( DefId , Ty < ' tcx > ) > > ,
175
+ // Anonymized types found in explicit return types, their param
176
+ // space of definition (TypeSpace in associated types, FnSpace in
177
+ // function return types) and their respective fresh inference
178
+ // variable. Writeback resolves these variables to get the concrete
179
+ // type, which can be used to deanonymize TyAnon, after typeck is
180
+ // done processing all functions.
181
+ anon_types : RefCell < Vec < ( DefId , ParamSpace , Ty < ' tcx > ) > > ,
180
182
}
181
183
182
184
trait DeferredCallResolution < ' tcx > {
@@ -364,6 +366,7 @@ fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
364
366
365
367
struct CheckItemTypesVisitor < ' a , ' tcx : ' a > { ccx : & ' a CrateCtxt < ' a , ' tcx > }
366
368
struct CheckItemBodiesVisitor < ' a , ' tcx : ' a > { ccx : & ' a CrateCtxt < ' a , ' tcx > }
369
+ struct CheckAnonTypesVisitor < ' a , ' tcx : ' a > { ccx : & ' a CrateCtxt < ' a , ' tcx > }
367
370
368
371
impl < ' a , ' tcx > Visitor < ' tcx > for CheckItemTypesVisitor < ' a , ' tcx > {
369
372
fn visit_item ( & mut self , i : & ' tcx ast:: Item ) {
@@ -390,6 +393,22 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
390
393
}
391
394
}
392
395
396
+ impl < ' a , ' tcx > Visitor < ' tcx > for CheckAnonTypesVisitor < ' a , ' tcx > {
397
+ fn visit_ty ( & mut self , ty : & ' tcx ast:: Ty ) {
398
+ if let ast:: TyAnon ( _) = ty. node {
399
+ if !self . ccx . tcx . tcache . borrow ( ) . contains_key ( & local_def ( ty. id ) ) {
400
+ span_err ! ( self . ccx. tcx. sess, ty. span, E0442 ,
401
+ "anonymized types must be used in a return \
402
+ type in the same impl") ;
403
+ }
404
+ }
405
+ visit:: walk_ty ( self , ty) ;
406
+ }
407
+
408
+ // Do not recurse into items.
409
+ fn visit_item ( & mut self , _: & ast:: Item ) { }
410
+ }
411
+
393
412
pub fn check_item_types ( ccx : & CrateCtxt ) {
394
413
let krate = ccx. tcx . map . krate ( ) ;
395
414
let mut visit = wf:: CheckTypeWellFormedVisitor :: new ( ccx) ;
@@ -425,6 +444,7 @@ pub fn check_item_types(ccx: &CrateCtxt) {
425
444
}
426
445
427
446
fn check_bare_fn < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
447
+ impl_id : Option < ast:: NodeId > ,
428
448
decl : & ' tcx ast:: FnDecl ,
429
449
body : & ' tcx ast:: Block ,
430
450
fn_id : ast:: NodeId ,
@@ -449,7 +469,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
449
469
& fn_sig) ;
450
470
451
471
let fcx = check_fn ( ccx, fn_ty. unsafety , fn_id, & fn_sig,
452
- decl, fn_id, body, & inh) ;
472
+ decl, impl_id , fn_id, body, & inh) ;
453
473
454
474
fcx. select_all_obligations_and_apply_defaults ( ) ;
455
475
upvar:: closure_analyze_fn ( & fcx, fn_id, decl, body) ;
@@ -559,6 +579,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
559
579
unsafety_id : ast:: NodeId ,
560
580
fn_sig : & ty:: FnSig < ' tcx > ,
561
581
decl : & ' tcx ast:: FnDecl ,
582
+ impl_id : Option < ast:: NodeId > ,
562
583
fn_id : ast:: NodeId ,
563
584
body : & ' tcx ast:: Block ,
564
585
inherited : & ' a Inherited < ' a , ' tcx > )
@@ -632,7 +653,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
632
653
633
654
check_block_with_expected ( & fcx, body, match ret_ty {
634
655
ty:: FnConverging ( result_type) => {
635
- ExpectHasType ( fcx. instantiate_anon_types ( result_type) )
656
+ ExpectHasType ( fcx. instantiate_anon_types ( result_type, fn_id , impl_id ) )
636
657
}
637
658
ty:: FnDiverging => NoExpectation
638
659
} ) ;
@@ -725,7 +746,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
725
746
ast:: ItemFn ( ref decl, _, _, _, _, ref body) => {
726
747
let fn_pty = ccx. tcx . lookup_item_type ( ast_util:: local_def ( it. id ) ) ;
727
748
let param_env = ParameterEnvironment :: for_item ( ccx. tcx , it. id ) ;
728
- check_bare_fn ( ccx, & * * decl, & * * body, it. id , it. span , fn_pty. ty , param_env) ;
749
+ check_bare_fn ( ccx, None , & * * decl, & * * body, it. id , it. span , fn_pty. ty , param_env) ;
729
750
}
730
751
ast:: ItemImpl ( _, _, _, _, _, ref impl_items) => {
731
752
debug ! ( "ItemImpl {} with id {}" , it. ident, it. id) ;
@@ -738,15 +759,23 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
738
759
check_const ( ccx, impl_item. span , & * expr, impl_item. id )
739
760
}
740
761
ast:: MethodImplItem ( ref sig, ref body) => {
741
- check_method_body ( ccx, & impl_pty. generics , sig, body ,
742
- impl_item. id , impl_item. span ) ;
762
+ check_method_body ( ccx, Some ( it . id ) , & impl_pty. generics , sig,
763
+ body , impl_item. id , impl_item. span ) ;
743
764
}
744
765
ast:: TypeImplItem ( _) |
745
766
ast:: MacImplItem ( _) => {
746
767
// Nothing to do here.
747
768
}
748
769
}
749
770
}
771
+
772
+ // Check that if we had anonymized types in an associated type,
773
+ // they were assigned by one of the methods in this impl.
774
+ for impl_item in impl_items {
775
+ if let ast:: TypeImplItem ( ref ty) = impl_item. node {
776
+ CheckAnonTypesVisitor { ccx : ccx } . visit_ty ( ty) ;
777
+ }
778
+ }
750
779
}
751
780
ast:: ItemTrait ( _, _, _, ref trait_items) => {
752
781
let trait_def = ccx. tcx . lookup_trait_def ( local_def ( it. id ) ) ;
@@ -758,8 +787,8 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
758
787
ast:: MethodTraitItem ( ref sig, Some ( ref body) ) => {
759
788
check_trait_fn_not_const ( ccx, trait_item. span , sig. constness ) ;
760
789
761
- check_method_body ( ccx, & trait_def. generics , sig, body ,
762
- trait_item. id , trait_item. span ) ;
790
+ check_method_body ( ccx, None , & trait_def. generics , sig,
791
+ body , trait_item. id , trait_item. span ) ;
763
792
}
764
793
ast:: MethodTraitItem ( ref sig, None ) => {
765
794
check_trait_fn_not_const ( ccx, trait_item. span , sig. constness ) ;
@@ -842,6 +871,7 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
842
871
/// * `self_bound`: bound for the `Self` type parameter, if any
843
872
/// * `method`: the method definition
844
873
fn check_method_body < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
874
+ impl_id : Option < ast:: NodeId > ,
845
875
item_generics : & ty:: Generics < ' tcx > ,
846
876
sig : & ' tcx ast:: MethodSig ,
847
877
body : & ' tcx ast:: Block ,
@@ -853,7 +883,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
853
883
let fty = ccx. tcx . node_id_to_type ( id) ;
854
884
debug ! ( "check_method_body: fty={:?}" , fty) ;
855
885
856
- check_bare_fn ( ccx, & sig. decl , body, id, span, fty, param_env) ;
886
+ check_bare_fn ( ccx, impl_id , & sig. decl , body, id, span, fty, param_env) ;
857
887
}
858
888
859
889
fn check_impl_items_against_trait < ' a , ' tcx > ( ccx : & CrateCtxt < ' a , ' tcx > ,
@@ -1363,15 +1393,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1363
1393
1364
1394
/// Replace all anonymized types with fresh inference variables
1365
1395
/// and record them for writeback.
1366
- fn instantiate_anon_types ( & self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1396
+ fn instantiate_anon_types ( & self , ty : Ty < ' tcx > , fn_id : ast:: NodeId ,
1397
+ impl_id : Option < ast:: NodeId > ) -> Ty < ' tcx > {
1367
1398
let tcx = self . tcx ( ) ;
1368
1399
let mut anon_types = self . inh . anon_types . borrow_mut ( ) ;
1369
1400
ty. fold_with ( & mut BottomUpFolder {
1370
1401
tcx : tcx,
1371
1402
fldop : |ty| {
1372
1403
if let ty:: TyAnon ( def_id, _, ref data) = ty. sty {
1404
+ // Do not instantiate an `impl Trait` type unless it was
1405
+ // defined in the same function's return type or in an
1406
+ // associated type of the impl, in the case of methods.
1407
+ if def_id. krate != ast:: LOCAL_CRATE {
1408
+ return ty;
1409
+ }
1410
+
1411
+ let parent = tcx. map . get_parent ( def_id. node ) ;
1412
+ let param_space = if parent == fn_id {
1413
+ subst:: FnSpace
1414
+ } else if Some ( tcx. map . get_parent ( parent) ) == impl_id {
1415
+ subst:: TypeSpace
1416
+ } else {
1417
+ return ty;
1418
+ } ;
1419
+
1373
1420
let ty_var = self . infcx ( ) . next_ty_var ( ) ;
1374
- anon_types. push ( ( def_id, ty_var) ) ;
1421
+ anon_types. push ( ( def_id, param_space , ty_var) ) ;
1375
1422
1376
1423
let span = tcx. map . def_id_span ( def_id, codemap:: DUMMY_SP ) ;
1377
1424
let cause = traits:: ObligationCause :: new ( span, self . body_id ,
0 commit comments