88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use rustc:: ty:: { self , subst , Ty } ;
12-
11+ use rustc:: ty:: { self , Ty } ;
12+ use rustc :: ty :: fold :: { TypeFoldable , TypeVisitor } ;
1313use std:: collections:: HashSet ;
1414
1515#[ derive( Clone , PartialEq , Eq , Hash , Debug ) ]
@@ -19,77 +19,53 @@ pub enum Parameter {
1919}
2020
2121/// If `include_projections` is false, returns the list of parameters that are
22- /// constrained by the type `ty ` - i.e. the value of each parameter in the list is
23- /// uniquely determined by `ty ` (see RFC 447). If it is true, return the list
22+ /// constrained by `t ` - i.e. the value of each parameter in the list is
23+ /// uniquely determined by `t ` (see RFC 447). If it is true, return the list
2424/// of parameters whose values are needed in order to constrain `ty` - these
2525/// differ, with the latter being a superset, in the presence of projections.
26- pub fn parameters_for_type < ' tcx > ( ty : Ty < ' tcx > ,
27- include_projections : bool ) -> Vec < Parameter > {
28- let mut result = vec ! [ ] ;
29- ty . maybe_walk ( |t| match t . sty {
30- ty :: TyProjection ( .. ) if !include_projections => {
26+ pub fn parameters_for < ' tcx , T > ( t : & T ,
27+ include_nonconstraining : bool )
28+ -> Vec < Parameter >
29+ where T : TypeFoldable < ' tcx >
30+ {
3131
32- false // projections are not injective.
33- }
34- _ => {
35- result. append ( & mut parameters_for_type_shallow ( t) ) ;
36- // non-projection type constructors are injective.
37- true
38- }
39- } ) ;
40- result
32+ let mut collector = ParameterCollector {
33+ parameters : vec ! [ ] ,
34+ include_nonconstraining : include_nonconstraining
35+ } ;
36+ t. visit_with ( & mut collector) ;
37+ collector. parameters
4138}
4239
43- pub fn parameters_for_trait_ref < ' tcx > ( trait_ref : & ty:: TraitRef < ' tcx > ,
44- include_projections : bool ) -> Vec < Parameter > {
45- let mut region_parameters =
46- parameters_for_regions_in_substs ( & trait_ref. substs ) ;
47-
48- let type_parameters =
49- trait_ref. substs
50- . types
51- . iter ( )
52- . flat_map ( |ty| parameters_for_type ( ty, include_projections) ) ;
53-
54- region_parameters. extend ( type_parameters) ;
55-
56- region_parameters
40+ struct ParameterCollector {
41+ parameters : Vec < Parameter > ,
42+ include_nonconstraining : bool
5743}
5844
59- fn parameters_for_type_shallow < ' tcx > ( ty : Ty < ' tcx > ) -> Vec < Parameter > {
60- match ty. sty {
61- ty:: TyParam ( ref d) =>
62- vec ! [ Parameter :: Type ( d. clone( ) ) ] ,
63- ty:: TyRef ( region, _) =>
64- parameters_for_region ( region) . into_iter ( ) . collect ( ) ,
65- ty:: TyStruct ( _, substs) |
66- ty:: TyEnum ( _, substs) =>
67- parameters_for_regions_in_substs ( substs) ,
68- ty:: TyTrait ( ref data) =>
69- parameters_for_regions_in_substs ( & data. principal . skip_binder ( ) . substs ) ,
70- ty:: TyProjection ( ref pi) =>
71- parameters_for_regions_in_substs ( & pi. trait_ref . substs ) ,
72- ty:: TyBool | ty:: TyChar | ty:: TyInt ( ..) | ty:: TyUint ( ..) |
73- ty:: TyFloat ( ..) | ty:: TyBox ( ..) | ty:: TyStr |
74- ty:: TyArray ( ..) | ty:: TySlice ( ..) |
75- ty:: TyFnDef ( ..) | ty:: TyFnPtr ( _) |
76- ty:: TyTuple ( ..) | ty:: TyRawPtr ( ..) |
77- ty:: TyInfer ( ..) | ty:: TyClosure ( ..) | ty:: TyError =>
78- vec ! [ ]
79- }
80- }
45+ impl < ' tcx > TypeVisitor < ' tcx > for ParameterCollector {
46+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
47+ match t. sty {
48+ ty:: TyProjection ( ..) if !self . include_nonconstraining => {
49+ // projections are not injective
50+ return false ;
51+ }
52+ ty:: TyParam ( ref d) => {
53+ self . parameters . push ( Parameter :: Type ( d. clone ( ) ) ) ;
54+ }
55+ _ => { }
56+ }
8157
82- fn parameters_for_regions_in_substs ( substs : & subst:: Substs ) -> Vec < Parameter > {
83- substs. regions
84- . iter ( )
85- . filter_map ( |r| parameters_for_region ( r) )
86- . collect ( )
87- }
58+ t. super_visit_with ( self )
59+ }
8860
89- fn parameters_for_region ( region : & ty:: Region ) -> Option < Parameter > {
90- match * region {
91- ty:: ReEarlyBound ( data) => Some ( Parameter :: Region ( data) ) ,
92- _ => None ,
61+ fn visit_region ( & mut self , r : ty:: Region ) -> bool {
62+ match r {
63+ ty:: ReEarlyBound ( data) => {
64+ self . parameters . push ( Parameter :: Region ( data) ) ;
65+ }
66+ _ => { }
67+ }
68+ false
9369 }
9470}
9571
@@ -191,12 +167,12 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
191167 // Then the projection only applies if `T` is known, but it still
192168 // does not determine `U`.
193169
194- let inputs = parameters_for_trait_ref ( & projection. projection_ty . trait_ref , true ) ;
170+ let inputs = parameters_for ( & projection. projection_ty . trait_ref , true ) ;
195171 let relies_only_on_inputs = inputs. iter ( ) . all ( |p| input_parameters. contains ( & p) ) ;
196172 if !relies_only_on_inputs {
197173 continue ;
198174 }
199- input_parameters. extend ( parameters_for_type ( projection. ty , false ) ) ;
175+ input_parameters. extend ( parameters_for ( & projection. ty , false ) ) ;
200176 } else {
201177 continue ;
202178 }
0 commit comments