42
42
43
43
use dep_graph:: DepGraph ;
44
44
use hir;
45
- use hir:: map:: { Definitions , DefKey } ;
46
- use hir:: def_id:: { DefIndex , DefId , CRATE_DEF_INDEX } ;
45
+ use hir:: HirVec ;
46
+ use hir:: map:: { Definitions , DefKey , DefPathData } ;
47
+ use hir:: def_id:: { DefIndex , DefId , CRATE_DEF_INDEX , DefIndexAddressSpace } ;
47
48
use hir:: def:: { Def , PathResolution } ;
48
49
use lint:: builtin:: PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES ;
49
50
use middle:: cstore:: CrateStore ;
@@ -52,7 +53,7 @@ use session::Session;
52
53
use util:: common:: FN_OUTPUT_NAME ;
53
54
use util:: nodemap:: { DefIdMap , FxHashMap , NodeMap } ;
54
55
55
- use std:: collections:: BTreeMap ;
56
+ use std:: collections:: { BTreeMap , HashSet } ;
56
57
use std:: fmt:: Debug ;
57
58
use std:: iter;
58
59
use std:: mem;
@@ -777,7 +778,24 @@ impl<'a> LoweringContext<'a> {
777
778
t. span , GateIssue :: Language ,
778
779
"`impl Trait` in return position is experimental" ) ;
779
780
}
780
- hir:: TyImplTraitExistential ( self . lower_bounds ( bounds, itctx) )
781
+ let def_index = self . resolver . definitions ( ) . opt_def_index ( t. id ) . unwrap ( ) ;
782
+ let hir_bounds = self . lower_bounds ( bounds, itctx) ;
783
+ let ( lifetimes, lifetime_defs) =
784
+ self . lifetimes_from_impl_trait_bounds ( def_index, & hir_bounds) ;
785
+
786
+ hir:: TyImplTraitExistential ( hir:: ExistTy {
787
+ generics : hir:: Generics {
788
+ lifetimes : lifetime_defs,
789
+ // Type parameters are taken from environment:
790
+ ty_params : Vec :: new ( ) . into ( ) ,
791
+ where_clause : hir:: WhereClause {
792
+ id : self . next_id ( ) . node_id ,
793
+ predicates : Vec :: new ( ) . into ( ) ,
794
+ } ,
795
+ span : t. span ,
796
+ } ,
797
+ bounds : hir_bounds,
798
+ } , lifetimes)
781
799
} ,
782
800
ImplTraitContext :: Universal ( def_id) => {
783
801
let has_feature = self . sess . features . borrow ( ) . universal_impl_trait ;
@@ -808,6 +826,111 @@ impl<'a> LoweringContext<'a> {
808
826
} )
809
827
}
810
828
829
+ fn lifetimes_from_impl_trait_bounds (
830
+ & mut self ,
831
+ parent_index : DefIndex ,
832
+ bounds : & hir:: TyParamBounds
833
+ ) -> ( HirVec < hir:: Lifetime > , HirVec < hir:: LifetimeDef > ) {
834
+
835
+ // This visitor walks over impl trait bounds and creates defs for all lifetimes which
836
+ // appear in the bounds, excluding lifetimes that are created within the bounds.
837
+ // e.g. 'a, 'b, but not 'c in `impl for<'c> SomeTrait<'a, 'b, 'c>`
838
+ struct ImplTraitLifetimeCollector < ' r , ' a : ' r > {
839
+ context : & ' r mut LoweringContext < ' a > ,
840
+ parent : DefIndex ,
841
+ currently_bound_lifetimes : Vec < Name > ,
842
+ already_defined_lifetimes : HashSet < Name > ,
843
+ output_lifetimes : Vec < hir:: Lifetime > ,
844
+ output_lifetime_defs : Vec < hir:: LifetimeDef > ,
845
+ }
846
+
847
+ impl < ' r , ' a : ' r , ' v > hir:: intravisit:: Visitor < ' v > for ImplTraitLifetimeCollector < ' r , ' a > {
848
+ fn nested_visit_map < ' this > ( & ' this mut self )
849
+ -> hir:: intravisit:: NestedVisitorMap < ' this , ' v > {
850
+ hir:: intravisit:: NestedVisitorMap :: None
851
+ }
852
+
853
+ fn visit_poly_trait_ref ( & mut self ,
854
+ polytr : & ' v hir:: PolyTraitRef ,
855
+ _: hir:: TraitBoundModifier ) {
856
+ let old_len = self . currently_bound_lifetimes . len ( ) ;
857
+
858
+ // Record the introduction of 'a in `for<'a> ...`
859
+ for lt_def in & polytr. bound_lifetimes {
860
+ // Introduce lifetimes one at a time so that we can handle
861
+ // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd> ...`
862
+ if let hir:: LifetimeName :: Name ( name) = lt_def. lifetime . name {
863
+ self . currently_bound_lifetimes . push ( name) ;
864
+ }
865
+
866
+ // Visit the lifetime bounds
867
+ for lt_bound in & lt_def. bounds {
868
+ self . visit_lifetime ( & lt_bound) ;
869
+ }
870
+ }
871
+
872
+ hir:: intravisit:: walk_trait_ref ( self , & polytr. trait_ref ) ;
873
+
874
+ self . currently_bound_lifetimes . truncate ( old_len) ;
875
+ }
876
+
877
+ fn visit_lifetime ( & mut self , lifetime : & ' v hir:: Lifetime ) {
878
+ // Exclude '_, 'static, and elided lifetimes (there should be no elided lifetimes)
879
+ if let hir:: LifetimeName :: Name ( lifetime_name) = lifetime. name {
880
+ if !self . currently_bound_lifetimes . contains ( & lifetime_name) &&
881
+ !self . already_defined_lifetimes . contains ( & lifetime_name)
882
+ {
883
+ self . already_defined_lifetimes . insert ( lifetime_name) ;
884
+ let name = hir:: LifetimeName :: Name ( lifetime_name) ;
885
+
886
+ self . output_lifetimes . push ( hir:: Lifetime {
887
+ id : self . context . next_id ( ) . node_id ,
888
+ span : lifetime. span ,
889
+ name,
890
+ } ) ;
891
+
892
+ let def_node_id = self . context . next_id ( ) . node_id ;
893
+ self . context . resolver . definitions ( ) . create_def_with_parent (
894
+ self . parent ,
895
+ def_node_id,
896
+ DefPathData :: LifetimeDef ( lifetime_name. as_str ( ) ) ,
897
+ DefIndexAddressSpace :: High ,
898
+ Mark :: root ( )
899
+ ) ;
900
+ let def_lifetime = hir:: Lifetime {
901
+ id : def_node_id,
902
+ span : lifetime. span ,
903
+ name,
904
+ } ;
905
+ self . output_lifetime_defs . push ( hir:: LifetimeDef {
906
+ lifetime : def_lifetime,
907
+ bounds : Vec :: new ( ) . into ( ) ,
908
+ pure_wrt_drop : false ,
909
+ } ) ;
910
+ }
911
+ }
912
+ }
913
+ }
914
+
915
+ let mut lifetime_collector = ImplTraitLifetimeCollector {
916
+ context : self ,
917
+ parent : parent_index,
918
+ currently_bound_lifetimes : Vec :: new ( ) ,
919
+ already_defined_lifetimes : HashSet :: new ( ) ,
920
+ output_lifetimes : Vec :: new ( ) ,
921
+ output_lifetime_defs : Vec :: new ( ) ,
922
+ } ;
923
+
924
+ for bound in bounds {
925
+ hir:: intravisit:: walk_ty_param_bound ( & mut lifetime_collector, & bound) ;
926
+ }
927
+
928
+ (
929
+ lifetime_collector. output_lifetimes . into ( ) ,
930
+ lifetime_collector. output_lifetime_defs . into ( )
931
+ )
932
+ }
933
+
811
934
fn lower_foreign_mod ( & mut self , fm : & ForeignMod ) -> hir:: ForeignMod {
812
935
hir:: ForeignMod {
813
936
abi : fm. abi ,
0 commit comments