@@ -45,7 +45,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
4545
4646 // forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
4747 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
4949 }
5050
5151 ty:: Dynamic ( ..) => {
@@ -166,8 +166,9 @@ crate fn program_clauses_for_env<'a, 'tcx>(
166166
167167crate fn environment < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> Environment < ' tcx > {
168168 use super :: { Lower , IntoFromEnvGoal } ;
169+ use rustc:: hir:: { Node , TraitItemKind , ImplItemKind , ItemKind , ForeignItemKind } ;
169170
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.
171172 if let Some ( parent) = ty:: is_impl_trait_defn ( tcx, def_id) {
172173 return environment ( tcx, parent) ;
173174 }
@@ -178,10 +179,71 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En
178179
179180 let clauses = predicates. into_iter ( )
180181 . 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.
183187 . map ( Clause :: ForAll ) ;
184188
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+
185247 Environment {
186248 clauses : tcx. mk_clauses ( clauses) ,
187249 }
0 commit comments