1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use chalk_engine::fallible::Fallible as ChalkEngineFallible;
12 use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
13 use rustc::infer::canonical::{Canonical, CanonicalVarValues, QueryRegionConstraint, QueryResult};
14 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
25 use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
26 use rustc::ty::subst::Kind;
27 use rustc::ty::{self, TyCtxt};
28 use smallvec::SmallVec;
30 use std::fmt::{self, Debug};
31 use std::marker::PhantomData;
33 use syntax_pos::DUMMY_SP;
35 #[derive(Copy, Clone, Debug)]
36 crate struct ChalkArenas<'gcx> {
37 _phantom: PhantomData<&'gcx ()>,
40 #[derive(Copy, Clone)]
41 crate struct ChalkContext<'cx, 'gcx: 'cx> {
42 _arenas: ChalkArenas<'gcx>,
43 _tcx: TyCtxt<'cx, 'gcx, 'gcx>,
46 #[derive(Copy, Clone)]
47 crate struct ChalkInferenceContext<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
48 infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
51 #[derive(Copy, Clone, Debug)]
52 crate struct UniverseMap;
54 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
55 crate struct ConstrainedSubst<'tcx> {
56 subst: CanonicalVarValues<'tcx>,
57 constraints: Vec<QueryRegionConstraint<'tcx>>,
60 BraceStructTypeFoldableImpl! {
61 impl<'tcx> TypeFoldable<'tcx> for ConstrainedSubst<'tcx> {
66 impl context::Context for ChalkArenas<'tcx> {
67 type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
69 type CanonicalGoalInEnvironment = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Goal<'tcx>>>;
71 // u-canonicalization not yet implemented
72 type UCanonicalGoalInEnvironment = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Goal<'tcx>>>;
74 type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
76 // u-canonicalization not yet implemented
77 type UniverseMap = UniverseMap;
79 type Solution = Canonical<'tcx, QueryResult<'tcx, ()>>;
81 type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
83 type GoalInEnvironment = ty::ParamEnvAnd<'tcx, Goal<'tcx>>;
85 type RegionConstraint = QueryRegionConstraint<'tcx>;
87 type Substitution = CanonicalVarValues<'tcx>;
89 type Environment = ty::ParamEnv<'tcx>;
91 type Goal = Goal<'tcx>;
93 type DomainGoal = DomainGoal<'tcx>;
95 type BindersGoal = ty::Binder<&'tcx Goal<'tcx>>;
97 type Parameter = Kind<'tcx>;
99 type ProgramClause = ProgramClause<'tcx>;
101 type ProgramClauses = Vec<ProgramClause<'tcx>>;
103 type UnificationResult = InferOk<'tcx, ()>;
105 fn into_goal(domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
106 Goal::DomainGoal(domain_goal)
109 fn cannot_prove() -> Goal<'tcx> {
113 fn goal_in_environment(
114 env: &ty::ParamEnv<'tcx>,
116 ) -> ty::ParamEnvAnd<'tcx, Goal<'tcx>> {
121 impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
124 _root_goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
125 _simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
126 ) -> Option<Canonical<'gcx, QueryResult<'gcx, ()>>> {
131 impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
132 /// True if this is a coinductive goal -- e.g., proving an auto trait.
133 fn is_coinductive(&self, _goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>) -> bool {
137 /// Create an inference table for processing a new goal and instantiate that goal
138 /// in that context, returning "all the pieces".
140 /// More specifically: given a u-canonical goal `arg`, creates a
141 /// new inference table `T` and populates it with the universes
142 /// found in `arg`. Then, creates a substitution `S` that maps
143 /// each bound variable in `arg` to a fresh inference variable
147 /// - the substitution `S`
148 /// - the environment and goal found by substitution `S` into `arg`
149 fn instantiate_ucanonical_goal<R>(
151 _arg: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
152 _op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
157 fn instantiate_ex_clause<R>(
159 _num_universes: usize,
160 _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
161 _op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
166 /// True if this solution has no region constraints.
167 fn empty_constraints(ccs: &Canonical<'gcx, ConstrainedSubst<'gcx>>) -> bool {
168 ccs.value.constraints.is_empty()
171 fn inference_normalized_subst_from_ex_clause(
172 canon_ex_clause: &'a Canonical<'gcx, ChalkExClause<'gcx>>,
173 ) -> &'a CanonicalVarValues<'gcx> {
174 &canon_ex_clause.value.subst
177 fn inference_normalized_subst_from_subst(
178 canon_subst: &'a Canonical<'gcx, ConstrainedSubst<'gcx>>,
179 ) -> &'a CanonicalVarValues<'gcx> {
180 &canon_subst.value.subst
184 u_canon: &'a Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
185 ) -> &'a Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
189 fn is_trivial_substitution(
190 _u_canon: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
191 _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
196 fn num_universes(_: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>) -> usize {
200 /// Convert a goal G *from* the canonical universes *into* our
201 /// local universes. This will yield a goal G' that is the same
202 /// but for the universes of universally quantified names.
203 fn map_goal_from_canonical(
205 value: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
206 ) -> Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
207 *value // FIXME universe maps not implemented yet
210 fn map_subst_from_canonical(
212 value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
213 ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
214 value.clone() // FIXME universe maps not implemented yet
218 //impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
219 // for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
221 // fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
225 // fn is_trivial_substitution(
227 // canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
229 // let subst = &canonical_subst.value.subst;
230 // assert_eq!(self.canonical.variables.len(), subst.var_values.len());
233 // .iter_enumerated()
234 // .all(|(cvar, kind)| match kind.unpack() {
235 // Kind::Lifetime(r) => match r {
236 // ty::ReCanonical(cvar1) => cvar == cvar1,
239 // Kind::Type(ty) => match ty.sty {
240 // ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
246 // fn num_universes(&self) -> usize {
251 impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
252 for ChalkInferenceContext<'cx, 'gcx, 'tcx>
254 fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
256 Goal::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
257 Goal::And(left, right) => HhGoal::And(*left, *right),
258 Goal::Not(subgoal) => HhGoal::Not(*subgoal),
259 Goal::DomainGoal(d) => HhGoal::DomainGoal(d),
260 Goal::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
261 Goal::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
262 Goal::CannotProve => HhGoal::CannotProve,
268 _env: &ty::ParamEnv<'tcx>,
269 _clauses: Vec<ProgramClause<'tcx>>,
270 ) -> ty::ParamEnv<'tcx> {
271 panic!("FIXME no method to add clauses to ParamEnv yet")
275 impl context::ResolventOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
276 for ChalkInferenceContext<'cx, 'gcx, 'tcx>
280 _environment: &ty::ParamEnv<'tcx>,
281 _goal: &DomainGoal<'tcx>,
282 _subst: &CanonicalVarValues<'tcx>,
283 _clause: &ProgramClause<'tcx>,
284 ) -> chalk_engine::fallible::Fallible<Canonical<'gcx, ChalkExClause<'gcx>>> {
288 fn apply_answer_subst(
290 _ex_clause: ChalkExClause<'tcx>,
291 _selected_goal: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
292 _answer_table_goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
293 _canonical_answer_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
294 ) -> chalk_engine::fallible::Fallible<ChalkExClause<'tcx>> {
299 impl context::TruncateOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
300 for ChalkInferenceContext<'cx, 'gcx, 'tcx>
304 subgoal: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
305 ) -> Option<ty::ParamEnvAnd<'tcx, Goal<'tcx>>> {
306 Some(*subgoal) // FIXME we should truncate at some point!
311 subst: &CanonicalVarValues<'tcx>,
312 ) -> Option<CanonicalVarValues<'tcx>> {
313 Some(subst.clone()) // FIXME we should truncate at some point!
317 impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
318 for ChalkInferenceContext<'cx, 'gcx, 'tcx>
322 _environment: &ty::ParamEnv<'tcx>,
323 goal: &DomainGoal<'tcx>,
324 ) -> Vec<ProgramClause<'tcx>> {
325 use rustc::traits::WhereClause::*;
328 DomainGoal::Holds(Implemented(_trait_predicate)) => {
331 // - Trait definitions (implied bounds)
332 // - Implementations of the trait itself
336 DomainGoal::Holds(ProjectionEq(_projection_predicate)) => {
341 DomainGoal::Holds(RegionOutlives(_region_outlives)) => {
345 DomainGoal::Holds(TypeOutlives(_type_outlives)) => {
349 DomainGoal::WellFormed(WellFormed::Trait(_trait_predicate)) => {
350 // These come from -- the trait decl.
354 DomainGoal::WellFormed(WellFormed::Ty(_ty)) => panic!(),
356 DomainGoal::FromEnv(FromEnv::Trait(_trait_predicate)) => panic!(),
358 DomainGoal::FromEnv(FromEnv::Ty(_ty)) => panic!(),
360 DomainGoal::Normalize(_) => panic!(),
364 fn instantiate_binders_universally(
366 _arg: &ty::Binder<&'tcx Goal<'tcx>>,
368 panic!("FIXME -- universal instantiation needs sgrif's branch")
371 fn instantiate_binders_existentially(
373 arg: &ty::Binder<&'tcx Goal<'tcx>>,
375 let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var(
377 LateBoundRegionConversionTime::HigherRankedType,
383 fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
384 let string = format!("{:?}", self.infcx.resolve_type_vars_if_possible(value));
388 fn canonicalize_goal(
390 value: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
391 ) -> Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
392 let mut _orig_values = SmallVec::new();
393 self.infcx.canonicalize_query(value, &mut _orig_values)
396 fn canonicalize_ex_clause(
398 value: &ChalkExClause<'tcx>,
399 ) -> Canonical<'gcx, ChalkExClause<'gcx>> {
400 self.infcx.canonicalize_response(value)
403 fn canonicalize_constrained_subst(
405 subst: CanonicalVarValues<'tcx>,
406 constraints: Vec<QueryRegionConstraint<'tcx>>,
407 ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
408 self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints })
411 fn u_canonicalize_goal(
413 value: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
415 Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
418 (value.clone(), UniverseMap)
423 _value: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
424 ) -> Option<ty::ParamEnvAnd<'tcx, Goal<'tcx>>> {
425 panic!("goal inversion not yet implemented")
430 _environment: &ty::ParamEnv<'tcx>,
433 ) -> ChalkEngineFallible<InferOk<'tcx, ()>> {
437 fn sink_answer_subset(
439 value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
440 ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
444 fn lift_delayed_literal(
446 _value: DelayedLiteral<ChalkArenas<'tcx>>,
447 ) -> DelayedLiteral<ChalkArenas<'gcx>> {
451 fn into_ex_clause(&mut self, _result: InferOk<'tcx, ()>, _ex_clause: &mut ChalkExClause<'tcx>) {
456 type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>;
458 type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>;
460 impl Debug for ChalkContext<'cx, 'gcx> {
461 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
462 write!(f, "ChalkContext")
466 impl Debug for ChalkInferenceContext<'cx, 'gcx, 'tcx> {
467 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
468 write!(f, "ChalkInferenceContext")
472 impl ExClauseLift<'gcx> for ChalkArenas<'a> {
473 type LiftedExClause = ChalkExClause<'gcx>;
475 fn lift_ex_clause_to_tcx(
476 _ex_clause: &ChalkExClause<'a>,
477 _tcx: TyCtxt<'_, '_, 'tcx>,
478 ) -> Option<Self::LiftedExClause> {
483 impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
484 fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(
485 ex_clause: &ChalkExClause<'tcx>,
487 ) -> ChalkExClause<'tcx> {
489 subst: ex_clause.subst.fold_with(folder),
490 delayed_literals: ex_clause.delayed_literals.fold_with(folder),
491 constraints: ex_clause.constraints.fold_with(folder),
492 subgoals: ex_clause.subgoals.fold_with(folder),
496 fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>(
497 ex_clause: &ExClause<Self>,
506 subst.visit_with(visitor)
507 && delayed_literals.visit_with(visitor)
508 && constraints.visit_with(visitor)
509 && subgoals.visit_with(visitor)
513 BraceStructLiftImpl! {
514 impl<'a, 'tcx> Lift<'tcx> for ConstrainedSubst<'a> {
515 type Lifted = ConstrainedSubst<'tcx>;