@@ -45,7 +45,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
45
45
46
46
// forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
47
47
ty:: Ref ( _region, _sub_ty, ..) => {
48
- // FIXME: we need bound tys in order to write the above rule
48
+ // FIXME: we'd need bound tys in order to properly write the above rule
49
49
}
50
50
51
51
ty:: Dynamic ( ..) => {
@@ -166,8 +166,9 @@ crate fn program_clauses_for_env<'a, 'tcx>(
166
166
167
167
crate fn environment < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> Environment < ' tcx > {
168
168
use super :: { Lower , IntoFromEnvGoal } ;
169
+ use rustc:: hir:: { Node , TraitItemKind , ImplItemKind , ItemKind , ForeignItemKind } ;
169
170
170
- // The environment of an impl Trait type is its defining function's environment
171
+ // The environment of an impl Trait type is its defining function's environment.
171
172
if let Some ( parent) = ty:: is_impl_trait_defn ( tcx, def_id) {
172
173
return environment ( tcx, parent) ;
173
174
}
@@ -178,10 +179,71 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En
178
179
179
180
let clauses = predicates. into_iter ( )
180
181
. map ( |predicate| predicate. lower ( ) )
181
- . map ( |domain_goal| domain_goal. map_bound ( |dg| dg. into_from_env_goal ( ) ) )
182
- . map ( |domain_goal| domain_goal. map_bound ( |dg| dg. into_program_clause ( ) ) )
182
+ . map ( |domain_goal| domain_goal. map_bound ( |bound| bound. into_from_env_goal ( ) ) )
183
+ . map ( |domain_goal| domain_goal. map_bound ( |bound| bound. into_program_clause ( ) ) )
184
+
185
+ // `ForAll` because each `domain_goal` is a `PolyDomainGoal` and
186
+ // could bound lifetimes.
183
187
. map ( Clause :: ForAll ) ;
184
188
189
+ let node_id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
190
+ let node = tcx. hir . get ( node_id) ;
191
+
192
+ let mut is_fn = false ;
193
+ let mut is_impl = false ;
194
+ match node {
195
+ Node :: TraitItem ( item) => match item. node {
196
+ TraitItemKind :: Method ( ..) => is_fn = true ,
197
+ _ => ( ) ,
198
+ }
199
+
200
+ Node :: ImplItem ( item) => match item. node {
201
+ ImplItemKind :: Method ( ..) => is_fn = true ,
202
+ _ => ( ) ,
203
+ }
204
+
205
+ Node :: Item ( item) => match item. node {
206
+ ItemKind :: Impl ( ..) => is_impl = true ,
207
+ ItemKind :: Fn ( ..) => is_fn = true ,
208
+ _ => ( ) ,
209
+ }
210
+
211
+ Node :: ForeignItem ( item) => match item. node {
212
+ ForeignItemKind :: Fn ( ..) => is_fn = true ,
213
+ _ => ( ) ,
214
+ }
215
+
216
+ // FIXME: closures?
217
+ _ => ( ) ,
218
+ }
219
+
220
+ let mut input_tys = FxHashSet :: default ( ) ;
221
+
222
+ // In an impl, we assume that the receiver type and all its constituents
223
+ // are well-formed.
224
+ if is_impl {
225
+ let trait_ref = tcx. impl_trait_ref ( def_id) . expect ( "not an impl" ) ;
226
+ input_tys. extend ( trait_ref. self_ty ( ) . walk ( ) ) ;
227
+ }
228
+
229
+ // In an fn, we assume that the arguments and all their constitutents are
230
+ // well-formed.
231
+ if is_fn {
232
+ let fn_sig = tcx. fn_sig ( def_id)
233
+ . no_late_bound_regions ( )
234
+ . expect ( "only early bound regions" ) ;
235
+ input_tys. extend (
236
+ fn_sig. inputs ( ) . iter ( ) . flat_map ( |ty| ty. walk ( ) )
237
+ ) ;
238
+ }
239
+
240
+ let clauses = clauses. chain (
241
+ input_tys. into_iter ( )
242
+ . map ( |ty| DomainGoal :: FromEnv ( FromEnv :: Ty ( ty) ) )
243
+ . map ( |domain_goal| domain_goal. into_program_clause ( ) )
244
+ . map ( Clause :: Implies )
245
+ ) ;
246
+
185
247
Environment {
186
248
clauses : tcx. mk_clauses ( clauses) ,
187
249
}
0 commit comments