1 use crate::forest
::Forest
;
2 use crate::slg
::SlgContextOps
;
3 use crate::{ExClause, Literal, TimeStamp}
;
5 use chalk_ir
::cast
::{Cast, Caster}
;
6 use chalk_ir
::interner
::Interner
;
8 Environment
, FallibleOrFloundered
, Goal
, GoalData
, InEnvironment
, QuantifierKind
, Substitution
,
9 TyKind
, TyVariableKind
, Variance
,
11 use chalk_solve
::infer
::InferenceTable
;
14 impl<I
: Interner
> Forest
<I
> {
15 /// Simplifies a goal into a series of positive domain goals
16 /// and negative goals. This operation may fail if the goal
17 /// includes unifications that cannot be completed.
18 pub(super) fn simplify_goal(
19 context
: &SlgContextOps
<I
>,
20 infer
: &mut InferenceTable
<I
>,
21 subst
: Substitution
<I
>,
22 initial_environment
: Environment
<I
>,
23 initial_goal
: Goal
<I
>,
24 ) -> FallibleOrFloundered
<ExClause
<I
>> {
25 let mut ex_clause
= ExClause
{
30 delayed_subgoals
: vec
![],
31 answer_time
: TimeStamp
::default(),
32 floundered_subgoals
: vec
![],
35 // A stack of higher-level goals to process.
36 let mut pending_goals
= vec
![(initial_environment
, initial_goal
)];
38 while let Some((environment
, goal
)) = pending_goals
.pop() {
39 match goal
.data(context
.program().interner()) {
40 GoalData
::Quantified(QuantifierKind
::ForAll
, subgoal
) => {
41 let subgoal
= infer
.instantiate_binders_universally(
42 context
.program().interner(),
45 pending_goals
.push((environment
, subgoal
.clone()));
47 GoalData
::Quantified(QuantifierKind
::Exists
, subgoal
) => {
48 let subgoal
= infer
.instantiate_binders_existentially(
49 context
.program().interner(),
52 pending_goals
.push((environment
, subgoal
.clone()));
54 GoalData
::Implies(wc
, subgoal
) => {
55 let new_environment
= environment
.add_clauses(
56 context
.program().interner(),
57 wc
.iter(context
.program().interner()).cloned(),
59 pending_goals
.push((new_environment
, subgoal
.clone()));
61 GoalData
::All(subgoals
) => {
62 for subgoal
in subgoals
.iter(context
.program().interner()) {
63 pending_goals
.push((environment
.clone(), subgoal
.clone()));
66 GoalData
::Not(subgoal
) => {
69 .push(Literal
::Negative(InEnvironment
::new(
74 GoalData
::EqGoal(goal
) => {
75 let interner
= context
.program().interner();
76 let db
= context
.unification_database();
81 match infer
.relate(interner
, db
, &environment
, Variance
::Invariant
, a
, b
) {
83 Err(_
) => return FallibleOrFloundered
::NoSolution
,
85 ex_clause
.subgoals
.extend(
90 .map(Literal
::Positive
),
93 GoalData
::SubtypeGoal(goal
) => {
94 let interner
= context
.program().interner();
95 let db
= context
.unification_database();
96 let a_norm
= infer
.normalize_ty_shallow(interner
, &goal
.a
);
97 let a
= a_norm
.as_ref().unwrap_or(&goal
.a
);
98 let b_norm
= infer
.normalize_ty_shallow(interner
, &goal
.b
);
99 let b
= b_norm
.as_ref().unwrap_or(&goal
.b
);
103 TyKind
::InferenceVar(_
, TyVariableKind
::General
)
106 TyKind
::InferenceVar(_
, TyVariableKind
::General
)
108 return FallibleOrFloundered
::Floundered
;
112 match infer
.relate(interner
, db
, &environment
, Variance
::Covariant
, a
, b
) {
114 Err(_
) => return FallibleOrFloundered
::Floundered
,
116 ex_clause
.subgoals
.extend(
121 .map(Literal
::Positive
),
124 GoalData
::DomainGoal(domain_goal
) => {
127 .push(Literal
::Positive(InEnvironment
::new(
129 domain_goal
.clone().cast(context
.program().interner()),
132 GoalData
::CannotProve
=> {
133 debug
!("Marking Strand as ambiguous because of a `CannotProve` subgoal");
134 ex_clause
.ambiguous
= true;
139 FallibleOrFloundered
::Ok(ex_clause
)