@@ -13,11 +13,10 @@ use rustc::traits::{
13
13
Clauses ,
14
14
DomainGoal ,
15
15
FromEnv ,
16
- Goal ,
17
16
ProgramClause ,
18
17
Environment ,
19
18
} ;
20
- use rustc:: ty:: { TyCtxt , Ty } ;
19
+ use rustc:: ty:: { self , TyCtxt , Ty } ;
21
20
use rustc_data_structures:: fx:: FxHashSet ;
22
21
23
22
struct ClauseVisitor < ' set , ' a , ' tcx : ' a > {
@@ -33,8 +32,63 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
33
32
}
34
33
}
35
34
36
- fn visit_ty ( & mut self , _ty : Ty < ' tcx > ) {
35
+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) {
36
+ match ty. sty {
37
+ ty:: Projection ( data) => {
38
+ self . round . extend (
39
+ self . tcx . program_clauses_for ( data. item_def_id )
40
+ . iter ( )
41
+ . cloned ( )
42
+ ) ;
43
+ }
44
+
45
+ // forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
46
+ ty:: Ref ( _region, _sub_ty, ..) => {
47
+ // FIXME: we need bound tys in order to write the above rule
48
+ }
49
+
50
+ ty:: Dynamic ( ..) => {
51
+ // FIXME: trait object rules are not yet implemented
52
+ }
53
+
54
+ ty:: Adt ( def, ..) => {
55
+ self . round . extend (
56
+ self . tcx . program_clauses_for ( def. did )
57
+ . iter ( )
58
+ . cloned ( )
59
+ ) ;
60
+ }
37
61
62
+ ty:: Foreign ( def_id) |
63
+ ty:: FnDef ( def_id, ..) |
64
+ ty:: Closure ( def_id, ..) |
65
+ ty:: Generator ( def_id, ..) |
66
+ ty:: Opaque ( def_id, ..) => {
67
+ self . round . extend (
68
+ self . tcx . program_clauses_for ( def_id)
69
+ . iter ( )
70
+ . cloned ( )
71
+ ) ;
72
+ }
73
+
74
+ ty:: Bool |
75
+ ty:: Char |
76
+ ty:: Int ( ..) |
77
+ ty:: Uint ( ..) |
78
+ ty:: Float ( ..) |
79
+ ty:: Str |
80
+ ty:: Array ( ..) |
81
+ ty:: Slice ( ..) |
82
+ ty:: RawPtr ( ..) |
83
+ ty:: FnPtr ( ..) |
84
+ ty:: Never |
85
+ ty:: Tuple ( ..) |
86
+ ty:: GeneratorWitness ( ..) |
87
+ ty:: UnnormalizedProjection ( ..) |
88
+ ty:: Param ( ..) |
89
+ ty:: Infer ( ..) |
90
+ ty:: Error => ( ) ,
91
+ }
38
92
}
39
93
40
94
fn visit_from_env ( & mut self , from_env : FromEnv < ' tcx > ) {
@@ -52,37 +106,20 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
52
106
}
53
107
54
108
fn visit_domain_goal ( & mut self , domain_goal : DomainGoal < ' tcx > ) {
109
+ // The only domain goals we can find in an environment are:
110
+ // * `DomainGoal::Holds(..)`
111
+ // * `DomainGoal::FromEnv(..)`
112
+ // The former do not lead to any implied bounds. So we only need
113
+ // to visit the latter.
55
114
if let DomainGoal :: FromEnv ( from_env) = domain_goal {
56
115
self . visit_from_env ( from_env) ;
57
116
}
58
117
}
59
118
60
- fn visit_goal ( & mut self , goal : Goal < ' tcx > ) {
61
- match goal {
62
- Goal :: Implies ( clauses, goal) => {
63
- for clause in clauses {
64
- self . visit_clause ( * clause) ;
65
- }
66
- self . visit_goal ( * goal) ;
67
- }
68
-
69
- Goal :: And ( goal1, goal2) => {
70
- self . visit_goal ( * goal1) ;
71
- self . visit_goal ( * goal2) ;
72
- }
73
-
74
- Goal :: Not ( goal) => self . visit_goal ( * goal) ,
75
- Goal :: DomainGoal ( domain_goal) => self . visit_domain_goal ( domain_goal) ,
76
- Goal :: Quantified ( _, goal) => self . visit_goal ( * * goal. skip_binder ( ) ) ,
77
- Goal :: CannotProve => ( ) ,
78
- }
79
- }
80
-
81
119
fn visit_program_clause ( & mut self , clause : ProgramClause < ' tcx > ) {
82
120
self . visit_domain_goal ( clause. goal ) ;
83
- for goal in clause. hypotheses {
84
- self . visit_goal ( * goal) ;
85
- }
121
+ // No need to visit `clause.hypotheses`: they are always of the form
122
+ // `FromEnv(...)` and were visited at a previous round.
86
123
}
87
124
88
125
fn visit_clause ( & mut self , clause : Clause < ' tcx > ) {
@@ -102,8 +139,8 @@ crate fn program_clauses_for_env<'a, 'tcx>(
102
139
let mut last_round = FxHashSet ( ) ;
103
140
{
104
141
let mut visitor = ClauseVisitor :: new ( tcx, & mut last_round) ;
105
- for clause in environment. clauses {
106
- visitor. visit_clause ( * clause) ;
142
+ for & clause in environment. clauses {
143
+ visitor. visit_clause ( clause) ;
107
144
}
108
145
}
109
146
0 commit comments