Skip to content

Commit 502d989

Browse files
committed
extend SLG solver with a similar optimization
1 parent a5083eb commit 502d989

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

chalk-engine/src/slg/aggregate.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,16 @@ impl<I: Interner> AggregateOps<I> for SlgContextOps<'_, I> {
4646
}
4747
};
4848

49+
// If the answer is trivially true and thus subsumes all others, then that's a unique-enough answer for us :)
50+
if subst.value.is_identity_subst_with_no_constraints(interner) {
51+
return Some(Solution::Unique(subst));
52+
}
53+
54+
tracing::debug!("subst = {:?}", subst);
55+
4956
// Exactly 1 unconditional answer?
5057
let next_answer = answers.peek_answer(&should_continue);
58+
tracing::debug!("next_answer = {:?}", next_answer);
5159
if next_answer.is_quantum_exceeded() {
5260
if subst.value.subst.is_identity_subst(interner) {
5361
return Some(Solution::Ambig(Guidance::Unknown));
@@ -83,9 +91,11 @@ impl<I: Interner> AggregateOps<I> for SlgContextOps<'_, I> {
8391
break Guidance::Unknown;
8492
}
8593

94+
// FIXME: This may cause us to miss some "trivially true" answers maybe? Haven't investigated very deeply.
8695
if !answers
8796
.any_future_answer(|ref mut new_subst| new_subst.may_invalidate(interner, &subst))
8897
{
98+
tracing::debug!("any_future_answer: false");
8999
break Guidance::Definite(subst);
90100
}
91101

@@ -96,7 +106,17 @@ impl<I: Interner> AggregateOps<I> for SlgContextOps<'_, I> {
96106
}
97107

98108
let new_subst = match answers.next_answer(&should_continue) {
99-
AnswerResult::Answer(answer1) => answer1.subst,
109+
AnswerResult::Answer(answer1) => {
110+
if answer1
111+
.subst
112+
.value
113+
.is_identity_subst_with_no_constraints(interner)
114+
{
115+
// If the answer is trivially true and thus subsumes all others, then that's a unique-enough answer for us :)
116+
return Some(Solution::Unique(answer1.subst));
117+
}
118+
answer1.subst
119+
}
100120
AnswerResult::Floundered => {
101121
// FIXME: this doesn't trigger for any current tests
102122
self.identity_constrained_subst(root_goal)
@@ -108,6 +128,7 @@ impl<I: Interner> AggregateOps<I> for SlgContextOps<'_, I> {
108128
break Guidance::Suggested(subst);
109129
}
110130
};
131+
tracing::debug!("new_subst = {:?}", new_subst);
111132
subst = merge_into_guidance(interner, &root_goal.canonical, subst, &new_subst);
112133
num_answers += 1;
113134
};

chalk-ir/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3048,6 +3048,15 @@ pub struct ConstrainedSubst<I: Interner> {
30483048
pub constraints: Constraints<I>,
30493049
}
30503050

3051+
impl<I: Interner> ConstrainedSubst<I> {
3052+
/// True if this is an identity subst (it maps variable 0 to variable 0 etc)
3053+
/// and has no constraints. This represents an "unconditionally true" answer which
3054+
/// is a convenient thing to recognize.
3055+
pub fn is_identity_subst_with_no_constraints(&self, interner: I) -> bool {
3056+
self.subst.is_identity_subst(interner) && self.constraints.is_empty(interner)
3057+
}
3058+
}
3059+
30513060
/// The resulting substitution after solving a goal.
30523061
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)]
30533062
pub struct AnswerSubst<I: Interner> {

chalk-solve/src/solve.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,9 @@ impl<I: Interner> Solution<I> {
103103

104104
pub fn is_trivial_and_always_true(&self, interner: I) -> bool {
105105
match self {
106-
Solution::Unique(constrained_subst) => {
107-
constrained_subst.value.subst.is_identity_subst(interner)
108-
&& constrained_subst.value.constraints.is_empty(interner)
109-
}
106+
Solution::Unique(constrained_subst) => constrained_subst
107+
.value
108+
.is_identity_subst_with_no_constraints(interner),
110109
Solution::Ambig(_) => false,
111110
}
112111
}

tests/test/misc.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -812,9 +812,7 @@ fn env_bound_vars() {
812812
WellFormed(&'a ())
813813
}
814814
}
815-
} yields[SolverChoice::slg_default()] {
816-
expect![["Ambiguous; definite substitution for<?U0> { [?0 := '^0.0] }"]]
817-
} yields[SolverChoice::recursive_default()] {
815+
} yields {
818816
expect![[r#"Unique; for<?U0> { substitution [?0 := '^0.0] }"#]]
819817
}
820818
goal {

0 commit comments

Comments
 (0)