@@ -6,7 +6,8 @@ use crate::stack::{Stack, StackIndex};
6
6
use crate :: strand:: { CanonicalStrand , SelectedSubgoal , Strand } ;
7
7
use crate :: table:: { AnswerIndex , Table } ;
8
8
use crate :: {
9
- Answer , AnswerMode , CompleteAnswer , ExClause , FlounderedSubgoal , Literal , Minimums , TableIndex , TimeStamp ,
9
+ Answer , AnswerMode , CompleteAnswer , ExClause , FlounderedSubgoal , Literal , Minimums , TableIndex ,
10
+ TimeStamp ,
10
11
} ;
11
12
use chalk_base:: results:: { Floundered , NoSolution } ;
12
13
@@ -22,7 +23,6 @@ type RootSearchResult<T> = Result<T, RootSearchFail>;
22
23
/// many strands) can fail. A root search is one that begins with an
23
24
/// empty stack.
24
25
#[ derive( Debug ) ]
25
- #[ must_use]
26
26
pub ( super ) enum RootSearchFail {
27
27
/// The table we were trying to solve cannot succeed.
28
28
NoMoreSolutions ,
@@ -278,7 +278,10 @@ impl<I: Interner, C: Context<I>> Forest<I, C> {
278
278
}
279
279
}
280
280
Err ( Floundered ) => {
281
- debug ! ( "Marking table {:?} as floundered! (failed to create program clauses)" , table_idx) ;
281
+ debug ! (
282
+ "Marking table {:?} as floundered! (failed to create program clauses)" ,
283
+ table_idx
284
+ ) ;
282
285
table. mark_floundered ( ) ;
283
286
}
284
287
}
@@ -491,8 +494,8 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
491
494
selected_subgoal,
492
495
last_pursued_time,
493
496
} = canonical_strand;
494
- let ( infer, ex_clause) = context
495
- . instantiate_ex_clause ( num_universes, & canonical_ex_clause) ;
497
+ let ( infer, ex_clause) =
498
+ context . instantiate_ex_clause ( num_universes, & canonical_ex_clause) ;
496
499
let strand = Strand {
497
500
infer,
498
501
ex_clause,
@@ -544,12 +547,14 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
544
547
// the selected subgoal of the strand.
545
548
// Now, we have to unify that answer onto the strand.
546
549
547
-
548
550
// If this answer is ambiguous and we don't want ambiguous answers
549
551
// yet, then we act like this is a floundered subgoal.
550
552
let ambiguous = {
551
553
let selected_subgoal = strand. selected_subgoal . as_ref ( ) . unwrap ( ) ;
552
- let answer = self . forest . answer ( selected_subgoal. subgoal_table , selected_subgoal. answer_index ) ;
554
+ let answer = self . forest . answer (
555
+ selected_subgoal. subgoal_table ,
556
+ selected_subgoal. answer_index ,
557
+ ) ;
553
558
answer. ambiguous
554
559
} ;
555
560
if let AnswerMode :: Complete = self . forest . tables [ self . stack . top ( ) . table ] . answer_mode {
@@ -925,7 +930,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
925
930
if let AnswerMode :: Complete = self . forest . tables [ self . stack . top ( ) . table ] . answer_mode {
926
931
if ambiguous {
927
932
// The strand can only return an ambiguous answer, but we don't
928
- // want that right noe , so requeue and we'll deal with it later.
933
+ // want that right now , so requeue and we'll deal with it later.
929
934
let canonical_strand = Forest :: canonicalize_strand ( self . context , strand) ;
930
935
self . forest . tables [ self . stack . top ( ) . table ] . enqueue_strand ( canonical_strand) ;
931
936
return NoRemainingSubgoalsResult :: RootSearchFail ( RootSearchFail :: QuantumExceeded ) ;
@@ -1061,7 +1066,10 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1061
1066
loop {
1062
1067
// This table is marked as floundered
1063
1068
let table = self . stack . top ( ) . table ;
1064
- debug ! ( "Marking table {:?} as floundered! (all subgoals floundered)" , table) ;
1069
+ debug ! (
1070
+ "Marking table {:?} as floundered! (all subgoals floundered)" ,
1071
+ table
1072
+ ) ;
1065
1073
self . forest . tables [ table] . mark_floundered ( ) ;
1066
1074
1067
1075
let mut strand = match self . stack . pop_and_take_caller_strand ( ) {
@@ -1148,41 +1156,46 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1148
1156
let forest = & mut self . forest ;
1149
1157
let context = & self . context ;
1150
1158
let strand_is_participating = |strand : & CanonicalStrand < I > | {
1151
- let ( _, ex_clause) = context
1152
- . instantiate_ex_clause ( num_universes, & strand. canonical_ex_clause ) ;
1159
+ let ( _, ex_clause) =
1160
+ context . instantiate_ex_clause ( num_universes, & strand. canonical_ex_clause ) ;
1153
1161
match ( table_answer_mode, ex_clause. ambiguous ) {
1154
1162
( AnswerMode :: Complete , true ) => false ,
1155
1163
( AnswerMode :: Complete , false ) => true ,
1156
1164
( AnswerMode :: Ambiguous , _) => true ,
1157
-
1158
1165
}
1159
1166
} ;
1160
- if forest. tables [ table] . strands_mut ( ) . any ( |s| strand_is_participating ( s) ) {
1167
+ // N.B. If we try to pursue a strand and it's found to be ambiguous,
1168
+ // we know that isn't part of a cycle.
1169
+ if forest. tables [ table]
1170
+ . strands_mut ( )
1171
+ . any ( |s| strand_is_participating ( s) )
1172
+ {
1161
1173
let clock = self . stack . top ( ) . clock ;
1162
1174
let cyclic_minimums = self . stack . top ( ) . cyclic_minimums ;
1163
1175
if cyclic_minimums. positive >= clock && cyclic_minimums. negative >= clock {
1164
1176
debug ! ( "cycle with no new answers" ) ;
1165
-
1177
+
1166
1178
if cyclic_minimums. negative < TimeStamp :: MAX {
1167
1179
// This is a negative cycle.
1168
1180
self . unwind_stack ( ) ;
1169
1181
return Err ( RootSearchFail :: NegativeCycle ) ;
1170
1182
}
1171
-
1183
+
1172
1184
// If all the things that we recursively depend on have
1173
1185
// positive dependencies on things below us in the stack,
1174
1186
// then no more answers are forthcoming. We can clear all
1175
1187
// the strands for those things recursively.
1176
1188
let table = self . stack . top ( ) . table ;
1177
- let cyclic_strands = self . forest . tables [ table] . drain_strands ( strand_is_participating) ;
1189
+ let cyclic_strands =
1190
+ self . forest . tables [ table] . drain_strands ( strand_is_participating) ;
1178
1191
self . clear_strands_after_cycle ( cyclic_strands) ;
1179
-
1192
+
1180
1193
// Now we yield with `QuantumExceeded`
1181
1194
self . unwind_stack ( ) ;
1182
1195
return Err ( RootSearchFail :: QuantumExceeded ) ;
1183
1196
} else {
1184
1197
debug ! ( "table part of a cycle" ) ;
1185
-
1198
+
1186
1199
// This table resulted in a positive cycle, so we have
1187
1200
// to check what this means for the subgoal containing
1188
1201
// this strand
@@ -1192,7 +1205,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1192
1205
panic ! ( "nothing on the stack but cyclic result" ) ;
1193
1206
}
1194
1207
} ;
1195
-
1208
+
1196
1209
// We can't take this because we might need it later to clear the cycle
1197
1210
let caller_selected_subgoal = caller_strand. selected_subgoal . as_ref ( ) . unwrap ( ) ;
1198
1211
match caller_strand. ex_clause . subgoals [ caller_selected_subgoal. subgoal_index ] {
@@ -1215,13 +1228,14 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1215
1228
self . stack . top ( ) . cyclic_minimums . take_minimums ( & mins) ;
1216
1229
}
1217
1230
}
1218
-
1231
+
1219
1232
// We can't pursue this strand anymore, so push it back onto the table
1220
1233
let active_strand = self . stack . top ( ) . active_strand . take ( ) . unwrap ( ) ;
1221
1234
let table = self . stack . top ( ) . table ;
1222
- let canonical_active_strand = Forest :: canonicalize_strand ( self . context , active_strand) ;
1235
+ let canonical_active_strand =
1236
+ Forest :: canonicalize_strand ( self . context , active_strand) ;
1223
1237
self . forest . tables [ table] . enqueue_strand ( canonical_active_strand) ;
1224
-
1238
+
1225
1239
// The strand isn't active, but the table is, so just continue
1226
1240
return Ok ( ( ) ) ;
1227
1241
}
@@ -1236,7 +1250,6 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1236
1250
}
1237
1251
AnswerMode :: Ambiguous => {
1238
1252
panic ! ( ) ;
1239
-
1240
1253
}
1241
1254
}
1242
1255
}
@@ -1274,7 +1287,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1274
1287
let selected_subgoal = selected_subgoal. unwrap_or_else ( || {
1275
1288
panic ! (
1276
1289
"clear_strands_after_cycle invoked on strand in table \
1277
- without a selected subgoal: {:# ?}",
1290
+ without a selected subgoal: {:?}",
1278
1291
canonical_ex_clause,
1279
1292
)
1280
1293
} ) ;
@@ -1363,15 +1376,21 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1363
1376
let table = self . stack . top ( ) . table ;
1364
1377
let Strand {
1365
1378
mut infer,
1366
- ex_clause,
1379
+ ex_clause :
1380
+ ExClause {
1381
+ subst,
1382
+ constraints,
1383
+ ambiguous,
1384
+ subgoals,
1385
+ delayed_subgoals,
1386
+ answer_time : _,
1387
+ floundered_subgoals,
1388
+ } ,
1367
1389
selected_subgoal : _,
1368
- last_pursued_time,
1390
+ last_pursued_time : _ ,
1369
1391
} = strand;
1370
- assert ! ( ex_clause. subgoals. is_empty( ) ) ;
1371
- let floundered = !ex_clause. floundered_subgoals . is_empty ( ) ;
1372
- if floundered {
1373
- //return None;
1374
- }
1392
+ assert ! ( subgoals. is_empty( ) ) ;
1393
+ let floundered = !floundered_subgoals. is_empty ( ) ;
1375
1394
1376
1395
// If the answer gets too large, mark the table as floundered.
1377
1396
// This is the *most conservative* course. There are a few alternatives:
@@ -1390,36 +1409,11 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1390
1409
// Ultimately, the current decision to flounder the entire table mostly boils
1391
1410
// down to "it works as we expect for the current tests". And, we likely don't
1392
1411
// even *need* the added complexity just for potentially more answers.
1393
- if infer. answer_needs_truncation ( self . context . interner ( ) , & ex_clause . subst ) {
1412
+ if infer. answer_needs_truncation ( self . context . interner ( ) , & subst) {
1394
1413
self . forest . tables [ table] . mark_floundered ( ) ;
1395
1414
return None ;
1396
1415
}
1397
1416
1398
- if ex_clause. ambiguous || floundered {
1399
- let table = & mut self . forest . tables [ table] ;
1400
- if let AnswerMode :: Complete = table. answer_mode {
1401
- let canonical_strand = Forest :: canonicalize_strand_from (
1402
- self . context ,
1403
- & mut infer,
1404
- & ex_clause,
1405
- None ,
1406
- last_pursued_time,
1407
- ) ;
1408
- table. enqueue_strand ( canonical_strand) ;
1409
- return None ;
1410
- }
1411
- }
1412
-
1413
- let ExClause {
1414
- subst,
1415
- constraints,
1416
- ambiguous,
1417
- subgoals : _,
1418
- delayed_subgoals,
1419
- answer_time : _,
1420
- floundered_subgoals : _,
1421
- } = ex_clause;
1422
-
1423
1417
let table_goal = & self . forest . tables [ table] . table_goal ;
1424
1418
1425
1419
// FIXME: Avoid double canonicalization
@@ -1447,7 +1441,7 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1447
1441
debug ! ( "answer: table={:?}, subst={:?}" , table, subst) ;
1448
1442
}
1449
1443
1450
- let answer = Answer { subst, ambiguous : ambiguous || floundered } ;
1444
+ let answer = Answer { subst, ambiguous } ;
1451
1445
1452
1446
// A "trivial" answer is one that is 'just true for all cases'
1453
1447
// -- in other words, it gives no information back to the
@@ -1508,10 +1502,9 @@ impl<'forest, I: Interner, C: Context<I> + 'forest, CO: ContextOps<I, C> + 'fore
1508
1502
// is a *bit* suspect; e.g., those things in the environment
1509
1503
// must be backed by an impl *eventually*).
1510
1504
let is_trivial_answer = {
1511
- self
1512
- . context
1505
+ self . context
1513
1506
. is_trivial_substitution ( & self . forest . tables [ table] . table_goal , & answer. subst )
1514
- && answer. subst . value . constraints . is_empty ( )
1507
+ && answer. subst . value . constraints . is_empty ( )
1515
1508
} ;
1516
1509
1517
1510
if let Some ( answer_index) = self . forest . tables [ table] . push_answer ( answer) {
0 commit comments