4 use super::ChalkInferenceContext;
6 Clause, DomainGoal, Environment, FromEnv, ProgramClause, ProgramClauseCategory, WellFormed,
8 use rustc::ty::{self, TyCtxt};
9 use rustc_hir::def_id::DefId;
13 use self::primitive::*;
15 fn assemble_clauses_from_impls<'tcx>(
18 clauses: &mut Vec<Clause<'tcx>>,
20 tcx.for_each_impl(trait_def_id, |impl_def_id| {
21 clauses.extend(tcx.program_clauses_for(impl_def_id).into_iter().cloned());
25 fn assemble_clauses_from_assoc_ty_values<'tcx>(
28 clauses: &mut Vec<Clause<'tcx>>,
30 tcx.for_each_impl(trait_def_id, |impl_def_id| {
31 for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
32 clauses.extend(tcx.program_clauses_for(*def_id).into_iter().cloned());
37 impl ChalkInferenceContext<'cx, 'tcx> {
38 pub(super) fn program_clauses_impl(
40 environment: &Environment<'tcx>,
41 goal: &DomainGoal<'tcx>,
42 ) -> Vec<Clause<'tcx>> {
43 use rustc::infer::canonical::OriginalQueryValues;
44 use rustc::traits::WhereClause::*;
46 let goal = self.infcx.resolve_vars_if_possible(goal);
48 debug!("program_clauses(goal = {:?})", goal);
50 let mut clauses = match goal {
51 DomainGoal::Holds(Implemented(trait_predicate)) => {
53 // * implementations of the trait itself (rule `Implemented-From-Impl`)
54 // * the trait decl (rule `Implemented-From-Env`)
56 let mut clauses = vec![];
58 assemble_clauses_from_impls(self.infcx.tcx, trait_predicate.def_id(), &mut clauses);
60 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
61 assemble_builtin_sized_impls(
63 trait_predicate.def_id(),
64 trait_predicate.self_ty(),
69 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
70 let source = trait_predicate.self_ty();
71 let target = trait_predicate.trait_ref.substs.type_at(1);
72 assemble_builtin_unsize_impls(
74 trait_predicate.def_id(),
81 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().copy_trait() {
82 assemble_builtin_copy_clone_impls(
84 trait_predicate.def_id(),
85 trait_predicate.self_ty(),
90 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().clone_trait() {
91 // For all builtin impls, the conditions for `Copy` and
92 // `Clone` are the same.
93 assemble_builtin_copy_clone_impls(
95 trait_predicate.def_id(),
96 trait_predicate.self_ty(),
101 // FIXME: we need to add special rules for other builtin impls:
103 // * `FnOnce` / `FnMut` / `Fn`
107 // Rule `Implemented-From-Env` will be computed from the environment.
111 DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
113 // * the assoc type definition (rule `ProjectionEq-Placeholder`)
114 // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
115 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
116 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
121 .program_clauses_for(projection_predicate.projection_ty.item_def_id)
123 // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
124 .filter(|clause| clause.category() == ProgramClauseCategory::Other)
126 .collect::<Vec<_>>();
128 // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
129 // from the environment.
133 // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause`
134 // will register them as actual region constraints later.
135 DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => {
136 vec![Clause::Implies(ProgramClause {
138 hypotheses: ty::List::empty(),
139 category: ProgramClauseCategory::Other,
143 DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
144 // These come from -- the trait decl (rule `WellFormed-TraitRef`).
147 .program_clauses_for(trait_predicate.def_id())
149 // only select `WellFormed-TraitRef`
150 .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
155 DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
157 // * the associated type definition if `ty` refers to an unnormalized
158 // associated type (rule `WellFormed-AssocTy`)
159 // * custom rules for built-in types
160 // * the type definition otherwise (rule `WellFormed-Type`)
161 let clauses = match ty.kind {
162 ty::Projection(data) => self.infcx.tcx.program_clauses_for(data.item_def_id),
164 // These types are always WF.
172 | ty::Placeholder(..)
175 let wf_clause = ProgramClause {
177 hypotheses: ty::List::empty(),
178 category: ProgramClauseCategory::WellFormed,
180 let wf_clause = Clause::Implies(wf_clause);
182 self.infcx.tcx.mk_clauses(iter::once(wf_clause))
185 // Always WF (recall that we do not check for parameters to be WF).
186 ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
188 // Always WF (recall that we do not check for parameters to be WF).
189 ty::FnPtr(fn_ptr) => {
190 let fn_ptr = fn_ptr.skip_binder();
191 wf_clause_for_fn_ptr(
193 fn_ptr.inputs_and_output.len(),
200 // WF if inner type is `Sized`.
201 ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
203 // WF if inner type is `Sized`.
204 ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
206 // WF if all types but the last one are `Sized`.
207 ty::Tuple(types) => wf_clause_for_tuple(self.infcx.tcx, types.len()),
209 // WF if `sub_ty` outlives `region`.
210 ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
212 ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
215 // FIXME: no rules yet for trait objects
219 ty::Adt(def, ..) => self.infcx.tcx.program_clauses_for(def.did),
221 // FIXME: these are probably wrong
223 | ty::Closure(def_id, ..)
224 | ty::Generator(def_id, ..)
225 | ty::Opaque(def_id, ..) => self.infcx.tcx.program_clauses_for(def_id),
227 // Artificially trigger an ambiguity.
229 let tcx = self.infcx.tcx;
230 let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
234 .map(|ty| ProgramClause {
235 goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
236 hypotheses: ty::List::empty(),
237 category: ProgramClauseCategory::WellFormed,
239 .map(|clause| Clause::Implies(clause));
240 tcx.mk_clauses(clauses)
243 ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Bound(..) => {
244 bug!("unexpected type {:?}", ty)
250 .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
255 DomainGoal::FromEnv(FromEnv::Trait(..)) => {
257 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
258 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
259 // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
260 // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
262 // All of these rules are computed in the environment.
266 DomainGoal::FromEnv(FromEnv::Ty(..)) => {
267 // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
268 // comes from the environment).
272 DomainGoal::Normalize(projection_predicate) => {
273 // These come from -- assoc ty values (rule `Normalize-From-Impl`).
274 let mut clauses = vec![];
276 assemble_clauses_from_assoc_ty_values(
278 projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
286 debug!("program_clauses: clauses = {:?}", clauses);
287 debug!("program_clauses: adding clauses from environment = {:?}", environment);
289 let mut _orig_query_values = OriginalQueryValues::default();
290 let canonical_environment =
291 self.infcx.canonicalize_query(environment, &mut _orig_query_values).value;
292 let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
294 debug!("program_clauses: env_clauses = {:?}", env_clauses);
296 clauses.extend(env_clauses.into_iter().cloned());
297 clauses.extend(environment.clauses.iter().cloned());