10 ProgramClauseCategory,
13 use rustc::ty::{self, TyCtxt};
14 use rustc::hir::def_id::DefId;
15 use super::ChalkInferenceContext;
18 use self::primitive::*;
21 fn assemble_clauses_from_impls<'tcx>(
22 tcx: TyCtxt<'_, 'tcx>,
24 clauses: &mut Vec<Clause<'tcx>>
26 tcx.for_each_impl(trait_def_id, |impl_def_id| {
28 tcx.program_clauses_for(impl_def_id)
35 fn assemble_clauses_from_assoc_ty_values<'tcx>(
36 tcx: TyCtxt<'_, 'tcx>,
38 clauses: &mut Vec<Clause<'tcx>>
40 tcx.for_each_impl(trait_def_id, |impl_def_id| {
41 for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
43 tcx.program_clauses_for(*def_id)
51 impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
52 pub(super) fn program_clauses_impl(
54 environment: &Environment<'tcx>,
55 goal: &DomainGoal<'tcx>,
56 ) -> Vec<Clause<'tcx>> {
57 use rustc::traits::WhereClause::*;
58 use rustc::infer::canonical::OriginalQueryValues;
60 let goal = self.infcx.resolve_vars_if_possible(goal);
62 debug!("program_clauses(goal = {:?})", goal);
64 let mut clauses = match goal {
65 DomainGoal::Holds(Implemented(trait_predicate)) => {
67 // * implementations of the trait itself (rule `Implemented-From-Impl`)
68 // * the trait decl (rule `Implemented-From-Env`)
70 let mut clauses = vec![];
72 assemble_clauses_from_impls(
74 trait_predicate.def_id(),
78 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
79 assemble_builtin_sized_impls(
81 trait_predicate.def_id(),
82 trait_predicate.self_ty(),
87 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
88 let source = trait_predicate.self_ty();
89 let target = trait_predicate.trait_ref.substs.type_at(1);
90 assemble_builtin_unsize_impls(
92 trait_predicate.def_id(),
99 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().copy_trait() {
100 assemble_builtin_copy_clone_impls(
102 trait_predicate.def_id(),
103 trait_predicate.self_ty(),
108 if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().clone_trait() {
109 // For all builtin impls, the conditions for `Copy` and
110 // `Clone` are the same.
111 assemble_builtin_copy_clone_impls(
113 trait_predicate.def_id(),
114 trait_predicate.self_ty(),
119 // FIXME: we need to add special rules for other builtin impls:
121 // * `FnOnce` / `FnMut` / `Fn`
125 // Rule `Implemented-From-Env` will be computed from the environment.
129 DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
131 // * the assoc type definition (rule `ProjectionEq-Placeholder`)
132 // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
133 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
134 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
136 let clauses = self.infcx.tcx.program_clauses_for(
137 projection_predicate.projection_ty.item_def_id
140 // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
141 .filter(|clause| clause.category() == ProgramClauseCategory::Other)
144 .collect::<Vec<_>>();
146 // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
147 // from the environment.
151 // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause`
152 // will register them as actual region constraints later.
153 DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => {
154 vec![Clause::Implies(ProgramClause {
156 hypotheses: ty::List::empty(),
157 category: ProgramClauseCategory::Other,
161 DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
162 // These come from -- the trait decl (rule `WellFormed-TraitRef`).
163 self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
166 // only select `WellFormed-TraitRef`
167 .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
173 DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
175 // * the associated type definition if `ty` refers to an unnormalized
176 // associated type (rule `WellFormed-AssocTy`)
177 // * custom rules for built-in types
178 // * the type definition otherwise (rule `WellFormed-Type`)
179 let clauses = match ty.sty {
180 ty::Projection(data) => {
181 self.infcx.tcx.program_clauses_for(data.item_def_id)
184 // These types are always WF.
192 ty::Placeholder(..) |
195 let wf_clause = ProgramClause {
197 hypotheses: ty::List::empty(),
198 category: ProgramClauseCategory::WellFormed,
200 let wf_clause = Clause::Implies(wf_clause);
202 self.infcx.tcx.mk_clauses(iter::once(wf_clause))
205 // Always WF (recall that we do not check for parameters to be WF).
206 ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
208 // Always WF (recall that we do not check for parameters to be WF).
209 ty::FnPtr(fn_ptr) => {
210 let fn_ptr = fn_ptr.skip_binder();
211 wf_clause_for_fn_ptr(
213 fn_ptr.inputs_and_output.len(),
220 // WF if inner type is `Sized`.
221 ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
223 // WF if inner type is `Sized`.
224 ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
226 // WF if all types but the last one are `Sized`.
227 ty::Tuple(types) => wf_clause_for_tuple(
232 // WF if `sub_ty` outlives `region`.
233 ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
235 ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
238 // FIXME: no rules yet for trait objects
242 ty::Adt(def, ..) => {
243 self.infcx.tcx.program_clauses_for(def.did)
246 // FIXME: these are probably wrong
247 ty::Foreign(def_id) |
248 ty::Closure(def_id, ..) |
249 ty::Generator(def_id, ..) |
250 ty::Opaque(def_id, ..) => {
251 self.infcx.tcx.program_clauses_for(def_id)
254 // Artificially trigger an ambiguity.
256 let tcx = self.infcx.tcx;
257 let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
258 let clauses = types.iter()
260 .map(|ty| ProgramClause {
261 goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
262 hypotheses: ty::List::empty(),
263 category: ProgramClauseCategory::WellFormed,
265 .map(|clause| Clause::Implies(clause));
266 tcx.mk_clauses(clauses)
269 ty::GeneratorWitness(..) |
270 ty::UnnormalizedProjection(..) |
272 bug!("unexpected type {:?}", ty)
277 .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
282 DomainGoal::FromEnv(FromEnv::Trait(..)) => {
284 // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
285 // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
286 // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
287 // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
289 // All of these rules are computed in the environment.
293 DomainGoal::FromEnv(FromEnv::Ty(..)) => {
294 // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
295 // comes from the environment).
299 DomainGoal::Normalize(projection_predicate) => {
300 // These come from -- assoc ty values (rule `Normalize-From-Impl`).
301 let mut clauses = vec![];
303 assemble_clauses_from_assoc_ty_values(
305 projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
313 debug!("program_clauses: clauses = {:?}", clauses);
314 debug!("program_clauses: adding clauses from environment = {:?}", environment);
316 let mut _orig_query_values = OriginalQueryValues::default();
317 let canonical_environment = self.infcx.canonicalize_query(
319 &mut _orig_query_values
321 let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
323 debug!("program_clauses: env_clauses = {:?}", env_clauses);
325 clauses.extend(env_clauses.into_iter().cloned());
326 clauses.extend(environment.clauses.iter().cloned());