Skip to content

Commit 119ca84

Browse files
committed
Merge pursue_answers
1 parent 8c456fa commit 119ca84

File tree

2 files changed

+41
-75
lines changed

2 files changed

+41
-75
lines changed

chalk-engine/src/logic.rs

Lines changed: 40 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type RootSearchResult<T> = Result<T, RootSearchFail>;
2222
/// many strands) can fail. A root search is one that begins with an
2323
/// empty stack.
2424
#[derive(Debug)]
25+
#[must_use]
2526
pub(super) enum RootSearchFail {
2627
/// The table we were trying to solve cannot succeed.
2728
NoMoreSolutions,
@@ -277,7 +278,7 @@ impl<I: Interner, C: Context<I>> Forest<I, C> {
277278
}
278279
}
279280
Err(Floundered) => {
280-
debug!("Marking table {:?} as floundered!", table_idx);
281+
debug!("Marking table {:?} as floundered! (failed to create program clauses)", table_idx);
281282
table.mark_floundered();
282283
}
283284
}
@@ -594,6 +595,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
594595
// the SLG FACTOR operation, though NFTD just makes it
595596
// part of computing the SLG resolvent.
596597
if self.forest.answer(subgoal_table, answer_index).ambiguous {
598+
debug!("Marking Strand as ambiguous because answer to (positive) subgoal was ambiguous");
597599
ex_clause.ambiguous = true;
598600
}
599601

@@ -660,6 +662,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
660662
// We want to disproval the subgoal, but we
661663
// have an unconditional answer for the subgoal,
662664
// therefore we have failed to disprove it.
665+
debug!("Marking Strand as ambiguous because answer to (negative) subgoal was ambiguous");
663666
strand.ex_clause.ambiguous = true;
664667

665668
// Strand is ambigious.
@@ -890,14 +893,12 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
890893

891894
fn on_no_remaining_subgoals(&mut self, strand: Strand<I, C>) -> NoRemainingSubgoalsResult {
892895
let floundered = strand.ex_clause.floundered_subgoals.len() > 0;
893-
let possible_answer = if !floundered {
894-
debug!("no remaining subgoals for the table");
895-
self.pursue_answer(strand)
896-
} else {
896+
if floundered {
897897
debug!("all remaining subgoals floundered for the table");
898-
self.pursue_answer_from_floundered(strand)
898+
} else {
899+
debug!("no remaining subgoals for the table");
899900
};
900-
match possible_answer {
901+
match self.pursue_answer(strand) {
901902
Some(answer_index) => {
902903
debug!("answer is available");
903904

@@ -940,6 +941,14 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
940941
}
941942
}
942943
None => {
944+
if floundered {
945+
// The strand floundered when trying to select a subgoal.
946+
// This will always return a `RootSearchFail`, either because the
947+
// root table floundered or we yield with `QuantumExceeded`.
948+
return NoRemainingSubgoalsResult::RootSearchFail(
949+
self.on_subgoal_selection_flounder(),
950+
);
951+
}
943952
debug!("answer is not available (or not new)");
944953

945954
// This table ned nowhere of interest
@@ -1013,7 +1022,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
10131022
loop {
10141023
// This table is marked as floundered
10151024
let table = self.stack.top().table;
1016-
debug!("Marking table {:?} as floundered!", table);
1025+
debug!("Marking table {:?} as floundered! (all subgoals floundered)", table);
10171026
self.forest.tables[table].mark_floundered();
10181027

10191028
let mut strand = match self.stack.pop_and_take_caller_strand() {
@@ -1270,63 +1279,6 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
12701279
}
12711280
}
12721281

1273-
/// This strand has no subgoals left, but some have floundered.
1274-
/// It's still possible that we can get an ambiguous answer from it though
1275-
fn pursue_answer_from_floundered(&mut self, strand: Strand<I, C>) -> Option<AnswerIndex> {
1276-
let table = self.stack.top().table;
1277-
let Strand {
1278-
mut infer,
1279-
ex_clause:
1280-
ExClause {
1281-
subst,
1282-
constraints,
1283-
ambiguous: _,
1284-
subgoals,
1285-
delayed_subgoals,
1286-
answer_time: _,
1287-
floundered_subgoals: _,
1288-
},
1289-
selected_subgoal: _,
1290-
last_pursued_time: _,
1291-
} = strand;
1292-
assert!(subgoals.is_empty());
1293-
let subst = infer.canonicalize_answer_subst(
1294-
self.context.interner(),
1295-
subst,
1296-
constraints,
1297-
delayed_subgoals,
1298-
);
1299-
debug!(
1300-
"answer from floundered goal: table={:?}, subst={:?}",
1301-
table, subst
1302-
);
1303-
1304-
let answer = Answer {
1305-
subst,
1306-
ambiguous: true,
1307-
};
1308-
1309-
// If our answer gives trivial information on the canonicalized goal then we have nothing interesting
1310-
// to return.
1311-
let is_trivial_answer = self
1312-
.context
1313-
.is_trivial_substitution(&self.forest.tables[table].table_goal, &answer.subst)
1314-
&& answer.subst.value.constraints.is_empty();
1315-
1316-
if is_trivial_answer {
1317-
self.on_subgoal_selection_flounder();
1318-
None
1319-
} else {
1320-
if let Some(answer_index) = self.forest.tables[table].push_answer(answer) {
1321-
Some(answer_index)
1322-
} else {
1323-
info!("answer: not a new answer, returning None");
1324-
self.on_subgoal_selection_flounder();
1325-
None
1326-
}
1327-
}
1328-
}
1329-
13301282
/// Invoked when a strand represents an **answer**. This means
13311283
/// that the strand has no subgoals left. There are two possibilities:
13321284
///
@@ -1343,7 +1295,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
13431295
ExClause {
13441296
subst,
13451297
constraints,
1346-
ambiguous,
1298+
mut ambiguous,
13471299
subgoals,
13481300
delayed_subgoals,
13491301
answer_time: _,
@@ -1353,7 +1305,12 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
13531305
last_pursued_time: _,
13541306
} = strand;
13551307
assert!(subgoals.is_empty());
1356-
assert!(floundered_subgoals.is_empty());
1308+
let floundered = !floundered_subgoals.is_empty();
1309+
if floundered {
1310+
// If this Strand has floundered, then this is only a partial answer
1311+
debug!("Marking Answer as ambiguous because all subgoals floundered");
1312+
ambiguous = true;
1313+
}
13571314

13581315
// If the answer gets too large, mark the table as floundered.
13591316
// This is the *most conservative* course. There are a few alternatives:
@@ -1379,7 +1336,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
13791336

13801337
let table_goal = &self.forest.tables[table].table_goal;
13811338

1382-
//FIXME: Avoid double canonicalization
1339+
// FIXME: Avoid double canonicalization
13831340
let filtered_delayed_subgoals = delayed_subgoals
13841341
.into_iter()
13851342
.filter(|delayed_subgoal| {
@@ -1395,7 +1352,14 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
13951352
constraints,
13961353
filtered_delayed_subgoals,
13971354
);
1398-
debug!("answer: table={:?}, subst={:?}", table, subst);
1355+
if floundered {
1356+
debug!(
1357+
"answer from floundered Strand: table={:?}, subst={:?}",
1358+
table, subst
1359+
);
1360+
} else {
1361+
debug!("answer: table={:?}, subst={:?}", table, subst);
1362+
}
13991363

14001364
let answer = Answer { subst, ambiguous };
14011365

@@ -1458,15 +1422,16 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
14581422
// is a *bit* suspect; e.g., those things in the environment
14591423
// must be backed by an impl *eventually*).
14601424
let is_trivial_answer = {
1461-
!answer.ambiguous
1462-
&& self
1463-
.context
1464-
.is_trivial_substitution(&self.forest.tables[table].table_goal, &answer.subst)
1465-
&& answer.subst.value.constraints.is_empty()
1425+
self
1426+
.context
1427+
.is_trivial_substitution(&self.forest.tables[table].table_goal, &answer.subst)
1428+
&& answer.subst.value.constraints.is_empty()
14661429
};
14671430

14681431
if let Some(answer_index) = self.forest.tables[table].push_answer(answer) {
1469-
if is_trivial_answer {
1432+
// See above, if we have a *complete* and trivial answer, we don't
1433+
// want to follow any more strands
1434+
if !ambiguous && is_trivial_answer {
14701435
self.forest.tables[table].take_strands();
14711436
}
14721437

chalk-engine/src/simplify.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl<I: Interner, C: Context<I>> Forest<I, C> {
7575
)));
7676
}
7777
GoalData::CannotProve(()) => {
78+
debug!("Marking Strand as ambiguous because of a `CannotProve` subgoal");
7879
ex_clause.ambiguous = true;
7980
}
8081
}

0 commit comments

Comments
 (0)