8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use rustc:: ty:: { self , subst , Ty } ;
12
-
11
+ use rustc:: ty:: { self , Ty } ;
12
+ use rustc :: ty :: fold :: { TypeFoldable , TypeVisitor } ;
13
13
use std:: collections:: HashSet ;
14
14
15
15
#[ derive( Clone , PartialEq , Eq , Hash , Debug ) ]
@@ -19,77 +19,53 @@ pub enum Parameter {
19
19
}
20
20
21
21
/// 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
24
24
/// of parameters whose values are needed in order to constrain `ty` - these
25
25
/// 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
+ {
31
31
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
41
38
}
42
39
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
57
43
}
58
44
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
+ }
81
57
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
+ }
88
60
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
93
69
}
94
70
}
95
71
@@ -191,12 +167,12 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
191
167
// Then the projection only applies if `T` is known, but it still
192
168
// does not determine `U`.
193
169
194
- let inputs = parameters_for_trait_ref ( & projection. projection_ty . trait_ref , true ) ;
170
+ let inputs = parameters_for ( & projection. projection_ty . trait_ref , true ) ;
195
171
let relies_only_on_inputs = inputs. iter ( ) . all ( |p| input_parameters. contains ( & p) ) ;
196
172
if !relies_only_on_inputs {
197
173
continue ;
198
174
}
199
- input_parameters. extend ( parameters_for_type ( projection. ty , false ) ) ;
175
+ input_parameters. extend ( parameters_for ( & projection. ty , false ) ) ;
200
176
} else {
201
177
continue ;
202
178
}
0 commit comments