]> git.lizzy.rs Git - rust.git/blob - src/librustc_traits/chalk_context/program_clauses.rs
Improve some compiletest documentation
[rust.git] / src / librustc_traits / chalk_context / program_clauses.rs
1 use rustc::traits::{
2     WellFormed,
3     FromEnv,
4     DomainGoal,
5     GoalKind,
6     Clause,
7     Clauses,
8     ProgramClause,
9     ProgramClauseCategory,
10     Environment,
11 };
12 use rustc::ty;
13 use rustc::ty::subst::{InternalSubsts, Subst};
14 use rustc::hir;
15 use rustc::hir::def_id::DefId;
16 use rustc_target::spec::abi;
17 use super::ChalkInferenceContext;
18 use crate::lowering::Lower;
19 use crate::generic_types;
20 use std::iter;
21
22 fn assemble_clauses_from_impls<'tcx>(
23     tcx: ty::TyCtxt<'_, '_, 'tcx>,
24     trait_def_id: DefId,
25     clauses: &mut Vec<Clause<'tcx>>
26 ) {
27     tcx.for_each_impl(trait_def_id, |impl_def_id| {
28         clauses.extend(
29             tcx.program_clauses_for(impl_def_id)
30                 .into_iter()
31                 .cloned()
32         );
33     });
34 }
35
36 fn assemble_clauses_from_assoc_ty_values<'tcx>(
37     tcx: ty::TyCtxt<'_, '_, 'tcx>,
38     trait_def_id: DefId,
39     clauses: &mut Vec<Clause<'tcx>>
40 ) {
41     tcx.for_each_impl(trait_def_id, |impl_def_id| {
42         for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
43             clauses.extend(
44                 tcx.program_clauses_for(*def_id)
45                     .into_iter()
46                     .cloned()
47             );
48         }
49     });
50 }
51
52 fn assemble_builtin_sized_impls<'tcx>(
53     tcx: ty::TyCtxt<'_, '_, 'tcx>,
54     sized_def_id: DefId,
55     ty: ty::Ty<'tcx>,
56     clauses: &mut Vec<Clause<'tcx>>
57 ) {
58     let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
59         let clause = ProgramClause {
60             goal: ty::TraitPredicate {
61                 trait_ref: ty::TraitRef {
62                     def_id: sized_def_id,
63                     substs: tcx.mk_substs_trait(ty, &[]),
64                 },
65             }.lower(),
66             hypotheses: tcx.mk_goals(
67                 nested.iter()
68                     .cloned()
69                     .map(|nested_ty| ty::TraitRef {
70                         def_id: sized_def_id,
71                         substs: tcx.mk_substs_trait(nested_ty, &[]),
72                     })
73                     .map(|trait_ref| ty::TraitPredicate { trait_ref })
74                     .map(|pred| GoalKind::DomainGoal(pred.lower()))
75                     .map(|goal_kind| tcx.mk_goal(goal_kind))
76             ),
77             category: ProgramClauseCategory::Other,
78         };
79         // Bind innermost bound vars that may exist in `ty` and `nested`.
80         clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
81     };
82
83     match &ty.sty {
84         // Non parametric primitive types.
85         ty::Bool |
86         ty::Char |
87         ty::Int(..) |
88         ty::Uint(..) |
89         ty::Float(..) |
90         ty::Error |
91         ty::Never => push_builtin_impl(ty, &[]),
92
93         // These ones are always `Sized`.
94         &ty::Array(_, length) => {
95             push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
96         }
97         ty::RawPtr(ptr) => {
98             push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
99         }
100         &ty::Ref(_, _, mutbl) => {
101             push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
102         }
103         ty::FnPtr(fn_ptr) => {
104             let fn_ptr = fn_ptr.skip_binder();
105             let fn_ptr = generic_types::fn_ptr(
106                 tcx,
107                 fn_ptr.inputs_and_output.len(),
108                 fn_ptr.c_variadic,
109                 fn_ptr.unsafety,
110                 fn_ptr.abi
111             );
112             push_builtin_impl(fn_ptr, &[]);
113         }
114         &ty::FnDef(def_id, ..) => {
115             push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
116         }
117         &ty::Closure(def_id, ..) => {
118             push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
119         }
120         &ty::Generator(def_id, ..) => {
121             push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
122         }
123
124         // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
125         &ty::Tuple(type_list) => {
126             let type_list = generic_types::type_list(tcx, type_list.len());
127             push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
128         }
129
130         // Struct def
131         ty::Adt(adt_def, _) => {
132             let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
133             let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
134             let sized_constraint = adt_def.sized_constraint(tcx)
135                 .iter()
136                 .map(|ty| ty.subst(tcx, substs))
137                 .collect::<Vec<_>>();
138             push_builtin_impl(adt, &sized_constraint);
139         }
140
141         // Artificially trigger an ambiguity.
142         ty::Infer(..) => {
143             // Everybody can find at least two types to unify against:
144             // general ty vars, int vars and float vars.
145             push_builtin_impl(tcx.types.i32, &[]);
146             push_builtin_impl(tcx.types.u32, &[]);
147             push_builtin_impl(tcx.types.f32, &[]);
148             push_builtin_impl(tcx.types.f64, &[]);
149         }
150
151         ty::Projection(_projection_ty) => {
152             // FIXME: add builtin impls from the associated type values found in
153             // trait impls of `projection_ty.trait_ref(tcx)`.
154         }
155
156         // The `Sized` bound can only come from the environment.
157         ty::Param(..) |
158         ty::Placeholder(..) |
159         ty::UnnormalizedProjection(..) => (),
160
161         // Definitely not `Sized`.
162         ty::Foreign(..) |
163         ty::Str |
164         ty::Slice(..) |
165         ty::Dynamic(..) |
166         ty::Opaque(..) => (),
167
168         ty::Bound(..) |
169         ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
170     }
171 }
172
173 fn wf_clause_for_raw_ptr<'tcx>(
174     tcx: ty::TyCtxt<'_, '_, 'tcx>,
175     mutbl: hir::Mutability
176 ) -> Clauses<'tcx> {
177     let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
178
179     let wf_clause = ProgramClause {
180         goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
181         hypotheses: ty::List::empty(),
182         category: ProgramClauseCategory::WellFormed,
183     };
184     let wf_clause = Clause::Implies(wf_clause);
185
186     // `forall<T> { WellFormed(*const T). }`
187     tcx.mk_clauses(iter::once(wf_clause))
188 }
189
190 fn wf_clause_for_fn_ptr<'tcx>(
191     tcx: ty::TyCtxt<'_, '_, 'tcx>,
192     arity_and_output: usize,
193     c_variadic: bool,
194     unsafety: hir::Unsafety,
195     abi: abi::Abi
196 ) -> Clauses<'tcx> {
197     let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, c_variadic, unsafety, abi);
198
199     let wf_clause = ProgramClause {
200         goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
201         hypotheses: ty::List::empty(),
202         category: ProgramClauseCategory::WellFormed,
203     };
204     let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
205
206     // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
207     // where `n + 1` == `arity_and_output`
208     tcx.mk_clauses(iter::once(wf_clause))
209 }
210
211 fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
212     let ty = generic_types::bound(tcx, 0);
213     let slice_ty = tcx.mk_slice(ty);
214
215     let sized_trait = match tcx.lang_items().sized_trait() {
216         Some(def_id) => def_id,
217         None => return ty::List::empty(),
218     };
219     let sized_implemented = ty::TraitRef {
220         def_id: sized_trait,
221         substs: tcx.mk_substs_trait(ty, ty::List::empty()),
222     };
223     let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
224         trait_ref: sized_implemented
225     }.lower();
226
227     let wf_clause = ProgramClause {
228         goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
229         hypotheses: tcx.mk_goals(
230             iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
231         ),
232         category: ProgramClauseCategory::WellFormed,
233     };
234     let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
235
236     // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
237     tcx.mk_clauses(iter::once(wf_clause))
238 }
239
240 fn wf_clause_for_array<'tcx>(
241     tcx: ty::TyCtxt<'_, '_, 'tcx>,
242     length: &'tcx ty::Const<'tcx>
243 ) -> Clauses<'tcx> {
244     let ty = generic_types::bound(tcx, 0);
245     let array_ty = tcx.mk_ty(ty::Array(ty, length));
246
247     let sized_trait = match tcx.lang_items().sized_trait() {
248         Some(def_id) => def_id,
249         None => return ty::List::empty(),
250     };
251     let sized_implemented = ty::TraitRef {
252         def_id: sized_trait,
253         substs: tcx.mk_substs_trait(ty, ty::List::empty()),
254     };
255     let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
256         trait_ref: sized_implemented
257     }.lower();
258
259     let wf_clause = ProgramClause {
260         goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
261         hypotheses: tcx.mk_goals(
262             iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
263         ),
264         category: ProgramClauseCategory::WellFormed,
265     };
266     let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
267
268     // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
269     tcx.mk_clauses(iter::once(wf_clause))
270 }
271
272 fn wf_clause_for_tuple<'tcx>(
273     tcx: ty::TyCtxt<'_, '_, 'tcx>,
274     arity: usize
275 ) -> Clauses<'tcx> {
276     let type_list = generic_types::type_list(tcx, arity);
277     let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
278
279     let sized_trait = match tcx.lang_items().sized_trait() {
280         Some(def_id) => def_id,
281         None => return ty::List::empty(),
282     };
283
284     // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
285     // hypotheses is actually empty.
286     let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
287         .map(|ty| ty::TraitRef {
288             def_id: sized_trait,
289             substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
290         })
291         .map(|trait_ref| ty::TraitPredicate { trait_ref })
292         .map(|predicate| predicate.lower());
293
294     let wf_clause = ProgramClause {
295         goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
296         hypotheses: tcx.mk_goals(
297             sized_implemented.map(|domain_goal| {
298                 tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
299             })
300         ),
301         category: ProgramClauseCategory::WellFormed,
302     };
303     let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
304
305     // ```
306     // forall<T1, ..., Tn-1, Tn> {
307     //     WellFormed((T1, ..., Tn)) :-
308     //         Implemented(T1: Sized),
309     //         ...
310     //         Implemented(Tn-1: Sized).
311     // }
312     // ```
313     tcx.mk_clauses(iter::once(wf_clause))
314 }
315
316 fn wf_clause_for_ref<'tcx>(
317     tcx: ty::TyCtxt<'_, '_, 'tcx>,
318     mutbl: hir::Mutability
319 ) -> Clauses<'tcx> {
320     let region = tcx.mk_region(
321         ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
322     );
323     let ty = generic_types::bound(tcx, 1);
324     let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
325         ty,
326         mutbl,
327     });
328
329     let _outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
330     let wf_clause = ProgramClause {
331         goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
332         hypotheses: ty::List::empty(),
333
334         // FIXME: restore this later once we get better at handling regions
335         // hypotheses: tcx.mk_goals(
336         //     iter::once(tcx.mk_goal(outlives.into_goal()))
337         // ),
338         category: ProgramClauseCategory::WellFormed,
339     };
340     let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
341
342     // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
343     tcx.mk_clauses(iter::once(wf_clause))
344 }
345
346 fn wf_clause_for_fn_def<'tcx>(
347     tcx: ty::TyCtxt<'_, '_, 'tcx>,
348     def_id: DefId
349 ) -> Clauses<'tcx> {
350     let fn_def = generic_types::fn_def(tcx, def_id);
351
352     let wf_clause = ProgramClause {
353         goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
354         hypotheses: ty::List::empty(),
355         category: ProgramClauseCategory::WellFormed,
356     };
357     let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
358
359     // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
360     // where `def_id` maps to the `some_fn` function definition
361     tcx.mk_clauses(iter::once(wf_clause))
362 }
363
364 impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
365     pub(super) fn program_clauses_impl(
366         &self,
367         environment: &Environment<'tcx>,
368         goal: &DomainGoal<'tcx>,
369     ) -> Vec<Clause<'tcx>> {
370         use rustc::traits::WhereClause::*;
371         use rustc::infer::canonical::OriginalQueryValues;
372
373         let goal = self.infcx.resolve_type_vars_if_possible(goal);
374
375         debug!("program_clauses(goal = {:?})", goal);
376
377         let mut clauses = match goal {
378             DomainGoal::Holds(Implemented(trait_predicate)) => {
379                 // These come from:
380                 // * implementations of the trait itself (rule `Implemented-From-Impl`)
381                 // * the trait decl (rule `Implemented-From-Env`)
382
383                 let mut clauses = vec![];
384
385                 assemble_clauses_from_impls(
386                     self.infcx.tcx,
387                     trait_predicate.def_id(),
388                     &mut clauses
389                 );
390
391                 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
392                     assemble_builtin_sized_impls(
393                         self.infcx.tcx,
394                         trait_predicate.def_id(),
395                         trait_predicate.self_ty(),
396                         &mut clauses
397                     );
398                 }
399
400                 // FIXME: we need to add special rules for builtin impls:
401                 // * `Copy` / `Clone`
402                 // * `Sized`
403                 // * `Unsize`
404                 // * `Generator`
405                 // * `FnOnce` / `FnMut` / `Fn`
406                 // * trait objects
407                 // * auto traits
408
409                 // Rule `Implemented-From-Env` will be computed from the environment.
410                 clauses
411             }
412
413             DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
414                 // These come from:
415                 // * the assoc type definition (rule `ProjectionEq-Placeholder`)
416                 // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
417                 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
418                 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
419
420                 let clauses = self.infcx.tcx.program_clauses_for(
421                     projection_predicate.projection_ty.item_def_id
422                 ).into_iter()
423
424                     // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
425                     .filter(|clause| clause.category() == ProgramClauseCategory::Other)
426
427                     .cloned()
428                     .collect::<Vec<_>>();
429
430                 // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
431                 // from the environment.
432                 clauses
433             }
434
435             DomainGoal::Holds(RegionOutlives(..)) => {
436                 // These come from:
437                 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
438                 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
439
440                 // All of these rules are computed in the environment.
441                 vec![]
442             }
443
444             DomainGoal::Holds(TypeOutlives(..)) => {
445                 // These come from:
446                 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
447                 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
448
449                 // All of these rules are computed in the environment.
450                 vec![]
451             }
452
453             DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
454                 // These come from -- the trait decl (rule `WellFormed-TraitRef`).
455                 self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
456                     .into_iter()
457
458                     // only select `WellFormed-TraitRef`
459                     .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
460
461                     .cloned()
462                     .collect()
463             }
464
465             DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
466                 // These come from:
467                 // * the associated type definition if `ty` refers to an unnormalized
468                 //   associated type (rule `WellFormed-AssocTy`)
469                 // * custom rules for built-in types
470                 // * the type definition otherwise (rule `WellFormed-Type`)
471                 let clauses = match ty.sty {
472                     ty::Projection(data) => {
473                         self.infcx.tcx.program_clauses_for(data.item_def_id)
474                     }
475
476                     // These types are always WF.
477                     ty::Bool |
478                     ty::Char |
479                     ty::Int(..) |
480                     ty::Uint(..) |
481                     ty::Float(..) |
482                     ty::Str |
483                     ty::Param(..) |
484                     ty::Placeholder(..) |
485                     ty::Error |
486                     ty::Never => {
487                         let wf_clause = ProgramClause {
488                             goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
489                             hypotheses: ty::List::empty(),
490                             category: ProgramClauseCategory::WellFormed,
491                         };
492                         let wf_clause = Clause::Implies(wf_clause);
493
494                         self.infcx.tcx.mk_clauses(iter::once(wf_clause))
495                     }
496
497                     // Always WF (recall that we do not check for parameters to be WF).
498                     ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
499
500                     // Always WF (recall that we do not check for parameters to be WF).
501                     ty::FnPtr(fn_ptr) => {
502                         let fn_ptr = fn_ptr.skip_binder();
503                         wf_clause_for_fn_ptr(
504                             self.infcx.tcx,
505                             fn_ptr.inputs_and_output.len(),
506                             fn_ptr.c_variadic,
507                             fn_ptr.unsafety,
508                             fn_ptr.abi
509                         )
510                     }
511
512                     // WF if inner type is `Sized`.
513                     ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
514
515                     // WF if inner type is `Sized`.
516                     ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
517
518                     // WF if all types but the last one are `Sized`.
519                     ty::Tuple(types) => wf_clause_for_tuple(
520                         self.infcx.tcx,
521                         types.len()
522                     ),
523
524                     // WF if `sub_ty` outlives `region`.
525                     ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
526
527                     ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
528
529                     ty::Dynamic(..) => {
530                         // FIXME: no rules yet for trait objects
531                         ty::List::empty()
532                     }
533
534                     ty::Adt(def, ..) => {
535                         self.infcx.tcx.program_clauses_for(def.did)
536                     }
537
538                     // FIXME: these are probably wrong
539                     ty::Foreign(def_id) |
540                     ty::Closure(def_id, ..) |
541                     ty::Generator(def_id, ..) |
542                     ty::Opaque(def_id, ..) => {
543                         self.infcx.tcx.program_clauses_for(def_id)
544                     }
545
546                     // Artificially trigger an ambiguity.
547                     ty::Infer(..) => {
548                         let tcx = self.infcx.tcx;
549                         let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
550                         let clauses = types.iter()
551                             .cloned()
552                             .map(|ty| ProgramClause {
553                                 goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
554                                 hypotheses: ty::List::empty(),
555                                 category: ProgramClauseCategory::WellFormed,
556                             })
557                             .map(|clause| Clause::Implies(clause));
558                         tcx.mk_clauses(clauses)
559                     }
560
561                     ty::GeneratorWitness(..) |
562                     ty::UnnormalizedProjection(..) |
563                     ty::Bound(..) => {
564                         bug!("unexpected type {:?}", ty)
565                     }
566                 };
567
568                 clauses.into_iter()
569                     .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
570                     .cloned()
571                     .collect()
572             }
573
574             DomainGoal::FromEnv(FromEnv::Trait(..)) => {
575                 // These come from:
576                 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
577                 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
578                 // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
579                 //   `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
580
581                 // All of these rules are computed in the environment.
582                 vec![]
583             }
584
585             DomainGoal::FromEnv(FromEnv::Ty(..)) => {
586                 // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
587                 // comes from the environment).
588                 vec![]
589             }
590
591             DomainGoal::Normalize(projection_predicate) => {
592                 // These come from -- assoc ty values (rule `Normalize-From-Impl`).
593                 let mut clauses = vec![];
594
595                 assemble_clauses_from_assoc_ty_values(
596                     self.infcx.tcx,
597                     projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
598                     &mut clauses
599                 );
600
601                 clauses
602             }
603         };
604
605         debug!("program_clauses: clauses = {:?}", clauses);
606         debug!("program_clauses: adding clauses from environment = {:?}", environment);
607
608         let mut _orig_query_values = OriginalQueryValues::default();
609         let canonical_environment = self.infcx.canonicalize_query(
610             environment,
611             &mut _orig_query_values
612         ).value;
613         let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
614
615         debug!("program_clauses: env_clauses = {:?}", env_clauses);
616
617         clauses.extend(env_clauses.into_iter().cloned());
618         clauses.extend(environment.clauses.iter().cloned());
619         clauses
620     }
621 }