@@ -52,13 +52,17 @@ use middle::const_val::ConstVal;
52
52
use rustc_const_eval:: { eval_const_expr_partial, ConstEvalErr } ;
53
53
use rustc_const_eval:: EvalHint :: UncheckedExprHint ;
54
54
use rustc_const_eval:: ErrKind :: ErroneousReferencedConstant ;
55
+ use hir:: { self , SelfKind } ;
55
56
use hir:: def:: { self , Def } ;
56
57
use hir:: def_id:: DefId ;
58
+ use hir:: print as pprust;
57
59
use middle:: resolve_lifetime as rl;
60
+ use rustc:: lint;
58
61
use rustc:: ty:: subst:: { FnSpace , TypeSpace , SelfSpace , Subst , Substs , ParamSpace } ;
59
62
use rustc:: traits;
60
63
use rustc:: ty:: { self , Ty , TyCtxt , ToPredicate , TypeFoldable } ;
61
64
use rustc:: ty:: wf:: object_region_bounds;
65
+ use rustc_back:: slice;
62
66
use require_c_abi_if_variadic;
63
67
use rscope:: { self , UnelidableRscope , RegionScope , ElidableRscope ,
64
68
ObjectLifetimeDefaultRscope , ShiftedRscope , BindingRscope ,
@@ -74,10 +78,6 @@ use syntax::errors::DiagnosticBuilder;
74
78
use syntax:: feature_gate:: { GateIssue , emit_feature_err} ;
75
79
use syntax:: parse:: token:: { self , keywords} ;
76
80
77
- use rustc:: hir:: print as pprust;
78
- use rustc:: hir:: { self , SelfKind } ;
79
- use rustc_back:: slice;
80
-
81
81
pub trait AstConv < ' gcx , ' tcx > {
82
82
fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' a , ' gcx , ' tcx > ;
83
83
@@ -679,6 +679,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
679
679
PathParamMode :: Explicit ,
680
680
trait_def_id,
681
681
self_ty,
682
+ trait_ref. ref_id ,
682
683
trait_ref. path . segments . last ( ) . unwrap ( ) ,
683
684
poly_projections)
684
685
}
@@ -723,6 +724,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
723
724
span : Span ,
724
725
param_mode : PathParamMode ,
725
726
trait_def_id : DefId ,
727
+ trait_path_ref_id : ast:: NodeId ,
726
728
trait_segment : & hir:: PathSegment ,
727
729
mut projections : & mut Vec < ty:: PolyProjectionPredicate < ' tcx > > )
728
730
-> ty:: PolyTraitRef < ' tcx >
@@ -732,6 +734,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
732
734
param_mode,
733
735
trait_def_id,
734
736
None ,
737
+ trait_path_ref_id,
735
738
trait_segment,
736
739
projections)
737
740
}
@@ -742,6 +745,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
742
745
param_mode : PathParamMode ,
743
746
trait_def_id : DefId ,
744
747
self_ty : Option < Ty < ' tcx > > ,
748
+ path_id : ast:: NodeId ,
745
749
trait_segment : & hir:: PathSegment ,
746
750
poly_projections : & mut Vec < ty:: PolyProjectionPredicate < ' tcx > > )
747
751
-> ty:: PolyTraitRef < ' tcx >
@@ -770,7 +774,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
770
774
. filter_map ( |binding| {
771
775
// specify type to assert that error was already reported in Err case:
772
776
let predicate: Result < _ , ErrorReported > =
773
- self . ast_type_binding_to_poly_projection_predicate ( poly_trait_ref. clone ( ) ,
777
+ self . ast_type_binding_to_poly_projection_predicate ( path_id,
778
+ poly_trait_ref. clone ( ) ,
774
779
self_ty,
775
780
binding) ;
776
781
predicate. ok ( ) // ok to ignore Err() because ErrorReported (see above)
@@ -863,7 +868,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
863
868
( self . tcx ( ) . mk_substs ( substs) , assoc_bindings)
864
869
}
865
870
866
- fn ast_type_binding_to_poly_projection_predicate ( & self ,
871
+ fn ast_type_binding_to_poly_projection_predicate (
872
+ & self ,
873
+ path_id : ast:: NodeId ,
867
874
mut trait_ref : ty:: PolyTraitRef < ' tcx > ,
868
875
self_ty : Option < Ty < ' tcx > > ,
869
876
binding : & ConvertedBinding < ' tcx > )
@@ -887,6 +894,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
887
894
//
888
895
// We want to produce `<B as SuperTrait<int>>::T == foo`.
889
896
897
+ // Find any late-bound regions declared in `ty` that are not
898
+ // declared in the trait-ref. These are not wellformed.
899
+ //
900
+ // Example:
901
+ //
902
+ // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
903
+ // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
904
+ let late_bound_in_trait_ref = tcx. collect_constrained_late_bound_regions ( & trait_ref) ;
905
+ let late_bound_in_ty = tcx. collect_referenced_late_bound_regions ( & ty:: Binder ( binding. ty ) ) ;
906
+ debug ! ( "late_bound_in_trait_ref = {:?}" , late_bound_in_trait_ref) ;
907
+ debug ! ( "late_bound_in_ty = {:?}" , late_bound_in_ty) ;
908
+ for br in late_bound_in_ty. difference ( & late_bound_in_trait_ref) {
909
+ let br_name = match * br {
910
+ ty:: BrNamed ( _, name) => name,
911
+ _ => {
912
+ span_bug ! (
913
+ binding. span,
914
+ "anonymous bound region {:?} in binding but not trait ref" ,
915
+ br) ;
916
+ }
917
+ } ;
918
+ tcx. sess . add_lint (
919
+ lint:: builtin:: HR_LIFETIME_IN_ASSOC_TYPE ,
920
+ path_id,
921
+ binding. span ,
922
+ format ! ( "binding for associated type `{}` references lifetime `{}`, \
923
+ which does not appear in the trait input types",
924
+ binding. item_name, br_name) ) ;
925
+ }
926
+
890
927
// Simple case: X is defined in the current trait.
891
928
if self . trait_defines_associated_type_named ( trait_ref. def_id ( ) , binding. item_name ) {
892
929
return Ok ( ty:: Binder ( ty:: ProjectionPredicate { // <-------------------+
@@ -1012,6 +1049,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1012
1049
path. span ,
1013
1050
PathParamMode :: Explicit ,
1014
1051
trait_def_id,
1052
+ ty. id ,
1015
1053
path. segments . last ( ) . unwrap ( ) ,
1016
1054
& mut projection_bounds) ;
1017
1055
Ok ( ( trait_ref, projection_bounds) )
@@ -1416,6 +1454,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1416
1454
param_mode : PathParamMode ,
1417
1455
def : Def ,
1418
1456
opt_self_ty : Option < Ty < ' tcx > > ,
1457
+ base_path_ref_id : ast:: NodeId ,
1419
1458
base_segments : & [ hir:: PathSegment ] )
1420
1459
-> Ty < ' tcx > {
1421
1460
let tcx = self . tcx ( ) ;
@@ -1434,6 +1473,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1434
1473
span,
1435
1474
param_mode,
1436
1475
trait_def_id,
1476
+ base_path_ref_id,
1437
1477
base_segments. last ( ) . unwrap ( ) ,
1438
1478
& mut projection_bounds) ;
1439
1479
@@ -1518,6 +1558,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1518
1558
param_mode : PathParamMode ,
1519
1559
mut def : Def ,
1520
1560
opt_self_ty : Option < Ty < ' tcx > > ,
1561
+ base_path_ref_id : ast:: NodeId ,
1521
1562
base_segments : & [ hir:: PathSegment ] ,
1522
1563
assoc_segments : & [ hir:: PathSegment ] )
1523
1564
-> ( Ty < ' tcx > , Def ) {
@@ -1532,6 +1573,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1532
1573
param_mode,
1533
1574
def,
1534
1575
opt_self_ty,
1576
+ base_path_ref_id,
1535
1577
base_segments) ;
1536
1578
debug ! ( "finish_resolving_def_to_ty: base_def_to_ty returned {:?}" , ty) ;
1537
1579
// If any associated type segments remain, attempt to resolve them.
@@ -1607,7 +1649,45 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1607
1649
}
1608
1650
hir:: TyBareFn ( ref bf) => {
1609
1651
require_c_abi_if_variadic ( tcx, & bf. decl , bf. abi , ast_ty. span ) ;
1610
- tcx. mk_fn_ptr ( self . ty_of_bare_fn ( bf. unsafety , bf. abi , & bf. decl ) )
1652
+ let bare_fn_ty = self . ty_of_bare_fn ( bf. unsafety , bf. abi , & bf. decl ) ;
1653
+
1654
+ // Find any late-bound regions declared in return type that do
1655
+ // not appear in the arguments. These are not wellformed.
1656
+ //
1657
+ // Example:
1658
+ //
1659
+ // for<'a> fn() -> &'a str <-- 'a is bad
1660
+ // for<'a> fn(&'a String) -> &'a str <-- 'a is ok
1661
+ //
1662
+ // Note that we do this check **here** and not in
1663
+ // `ty_of_bare_fn` because the latter is also used to make
1664
+ // the types for fn items, and we do not want to issue a
1665
+ // warning then. (Once we fix #32330, the regions we are
1666
+ // checking for here would be considered early bound
1667
+ // anyway.)
1668
+ let inputs = bare_fn_ty. sig . inputs ( ) ;
1669
+ let late_bound_in_args = tcx. collect_constrained_late_bound_regions ( & inputs) ;
1670
+ let output = bare_fn_ty. sig . output ( ) ;
1671
+ let late_bound_in_ret = tcx. collect_referenced_late_bound_regions ( & output) ;
1672
+ for br in late_bound_in_ret. difference ( & late_bound_in_args) {
1673
+ let br_name = match * br {
1674
+ ty:: BrNamed ( _, name) => name,
1675
+ _ => {
1676
+ span_bug ! (
1677
+ bf. decl. output. span( ) ,
1678
+ "anonymous bound region {:?} in return but not args" ,
1679
+ br) ;
1680
+ }
1681
+ } ;
1682
+ tcx. sess . add_lint (
1683
+ lint:: builtin:: HR_LIFETIME_IN_ASSOC_TYPE ,
1684
+ ast_ty. id ,
1685
+ ast_ty. span ,
1686
+ format ! ( "return type references lifetime `{}`, \
1687
+ which does not appear in the trait input types",
1688
+ br_name) ) ;
1689
+ }
1690
+ tcx. mk_fn_ptr ( bare_fn_ty)
1611
1691
}
1612
1692
hir:: TyPolyTraitRef ( ref bounds) => {
1613
1693
self . conv_ty_poly_trait_ref ( rscope, ast_ty. span , bounds)
@@ -1635,6 +1715,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1635
1715
PathParamMode :: Explicit ,
1636
1716
def,
1637
1717
opt_self_ty,
1718
+ ast_ty. id ,
1638
1719
& path. segments [ ..base_ty_end] ,
1639
1720
& path. segments [ base_ty_end..] ) ;
1640
1721
0 commit comments