@@ -22,6 +22,7 @@ type RootSearchResult<T> = Result<T, RootSearchFail>;
22
22
/// many strands) can fail. A root search is one that begins with an
23
23
/// empty stack.
24
24
#[ derive( Debug ) ]
25
+ #[ must_use]
25
26
pub ( super ) enum RootSearchFail {
26
27
/// The table we were trying to solve cannot succeed.
27
28
NoMoreSolutions ,
@@ -277,7 +278,7 @@ impl<I: Interner, C: Context<I>> Forest<I, C> {
277
278
}
278
279
}
279
280
Err ( Floundered ) => {
280
- debug ! ( "Marking table {:?} as floundered!" , table_idx) ;
281
+ debug ! ( "Marking table {:?} as floundered! (failed to create program clauses) " , table_idx) ;
281
282
table. mark_floundered ( ) ;
282
283
}
283
284
}
@@ -594,6 +595,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
594
595
// the SLG FACTOR operation, though NFTD just makes it
595
596
// part of computing the SLG resolvent.
596
597
if self . forest . answer ( subgoal_table, answer_index) . ambiguous {
598
+ debug ! ( "Marking Strand as ambiguous because answer to (positive) subgoal was ambiguous" ) ;
597
599
ex_clause. ambiguous = true ;
598
600
}
599
601
@@ -660,6 +662,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
660
662
// We want to disproval the subgoal, but we
661
663
// have an unconditional answer for the subgoal,
662
664
// therefore we have failed to disprove it.
665
+ debug ! ( "Marking Strand as ambiguous because answer to (negative) subgoal was ambiguous" ) ;
663
666
strand. ex_clause . ambiguous = true ;
664
667
665
668
// Strand is ambigious.
@@ -890,14 +893,12 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
890
893
891
894
fn on_no_remaining_subgoals ( & mut self , strand : Strand < I , C > ) -> NoRemainingSubgoalsResult {
892
895
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 {
897
897
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" ) ;
899
900
} ;
900
- match possible_answer {
901
+ match self . pursue_answer ( strand ) {
901
902
Some ( answer_index) => {
902
903
debug ! ( "answer is available" ) ;
903
904
@@ -940,6 +941,14 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
940
941
}
941
942
}
942
943
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
+ }
943
952
debug ! ( "answer is not available (or not new)" ) ;
944
953
945
954
// This table ned nowhere of interest
@@ -1013,7 +1022,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1013
1022
loop {
1014
1023
// This table is marked as floundered
1015
1024
let table = self . stack . top ( ) . table ;
1016
- debug ! ( "Marking table {:?} as floundered!" , table) ;
1025
+ debug ! ( "Marking table {:?} as floundered! (all subgoals floundered) " , table) ;
1017
1026
self . forest . tables [ table] . mark_floundered ( ) ;
1018
1027
1019
1028
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
1270
1279
}
1271
1280
}
1272
1281
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
-
1330
1282
/// Invoked when a strand represents an **answer**. This means
1331
1283
/// that the strand has no subgoals left. There are two possibilities:
1332
1284
///
@@ -1343,7 +1295,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1343
1295
ExClause {
1344
1296
subst,
1345
1297
constraints,
1346
- ambiguous,
1298
+ mut ambiguous,
1347
1299
subgoals,
1348
1300
delayed_subgoals,
1349
1301
answer_time : _,
@@ -1353,7 +1305,12 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1353
1305
last_pursued_time : _,
1354
1306
} = strand;
1355
1307
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
+ }
1357
1314
1358
1315
// If the answer gets too large, mark the table as floundered.
1359
1316
// 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
1379
1336
1380
1337
let table_goal = & self . forest . tables [ table] . table_goal ;
1381
1338
1382
- //FIXME: Avoid double canonicalization
1339
+ // FIXME: Avoid double canonicalization
1383
1340
let filtered_delayed_subgoals = delayed_subgoals
1384
1341
. into_iter ( )
1385
1342
. filter ( |delayed_subgoal| {
@@ -1395,7 +1352,14 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1395
1352
constraints,
1396
1353
filtered_delayed_subgoals,
1397
1354
) ;
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
+ }
1399
1363
1400
1364
let answer = Answer { subst, ambiguous } ;
1401
1365
@@ -1458,15 +1422,16 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1458
1422
// is a *bit* suspect; e.g., those things in the environment
1459
1423
// must be backed by an impl *eventually*).
1460
1424
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 ( )
1466
1429
} ;
1467
1430
1468
1431
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 {
1470
1435
self . forest . tables [ table] . take_strands ( ) ;
1471
1436
}
1472
1437
0 commit comments