1
- use crate :: infer:: {
2
- canonicalize:: Canonicalized , ucanonicalize:: UCanonicalized , unify:: UnificationResult ,
3
- InferenceTable , ParameterEnaVariable , ParameterEnaVariableExt ,
4
- } ;
5
- use crate :: recursive:: { Minimums , Solver } ;
6
- use crate :: solve:: { truncate, Guidance , Solution } ;
1
+ use crate :: infer:: { InferenceTable , ParameterEnaVariable , ParameterEnaVariableExt } ;
2
+ use crate :: recursive:: { Minimums , RecursiveInferenceTableImpl , Solver } ;
3
+ use crate :: solve:: { Guidance , Solution } ;
7
4
use chalk_ir:: cast:: Cast ;
8
5
use chalk_ir:: fold:: Fold ;
9
6
use chalk_ir:: interner:: { HasInterner , Interner } ;
7
+ use chalk_ir:: visit:: Visit ;
10
8
use chalk_ir:: zip:: Zip ;
11
9
use chalk_ir:: { debug, debug_heading} ;
12
10
use chalk_ir:: {
@@ -60,6 +58,69 @@ enum NegativeSolution {
60
58
Ambiguous ,
61
59
}
62
60
61
+ pub ( crate ) trait RecursiveInferenceTable < I : Interner > {
62
+ fn instantiate_binders_universally < ' a , T > (
63
+ & mut self ,
64
+ interner : & ' a I ,
65
+ arg : & ' a Binders < T > ,
66
+ ) -> T :: Result
67
+ where
68
+ T : Fold < I > + HasInterner < Interner = I > ;
69
+
70
+ fn instantiate_binders_existentially < ' a , T > (
71
+ & mut self ,
72
+ interner : & ' a I ,
73
+ arg : & ' a Binders < T > ,
74
+ ) -> T :: Result
75
+ where
76
+ T : Fold < I > + HasInterner < Interner = I > ;
77
+
78
+ fn canonicalize < T > (
79
+ & mut self ,
80
+ interner : & I ,
81
+ value : & T ,
82
+ ) -> ( Canonical < T :: Result > , Vec < ParameterEnaVariable < I > > )
83
+ where
84
+ T : Fold < I > ,
85
+ T :: Result : HasInterner < Interner = I > ;
86
+
87
+ fn u_canonicalize < T > (
88
+ & mut self ,
89
+ interner : & I ,
90
+ value0 : & Canonical < T > ,
91
+ ) -> ( UCanonical < T :: Result > , UniverseMap )
92
+ where
93
+ T : HasInterner < Interner = I > + Fold < I > + Visit < I > ,
94
+ T :: Result : HasInterner < Interner = I > ;
95
+
96
+ fn unify < T > (
97
+ & mut self ,
98
+ interner : & I ,
99
+ environment : & Environment < I > ,
100
+ a : & T ,
101
+ b : & T ,
102
+ ) -> Fallible < (
103
+ Vec < InEnvironment < DomainGoal < I > > > ,
104
+ Vec < InEnvironment < Constraint < I > > > ,
105
+ ) >
106
+ where
107
+ T : ?Sized + Zip < I > ;
108
+
109
+ fn instantiate_canonical < T > ( & mut self , interner : & I , bound : & Canonical < T > ) -> T :: Result
110
+ where
111
+ T : HasInterner < Interner = I > + Fold < I > + Debug ;
112
+
113
+ fn invert_then_canonicalize < T > (
114
+ & mut self ,
115
+ interner : & I ,
116
+ value : & T ,
117
+ ) -> Option < Canonical < T :: Result > >
118
+ where
119
+ T : Fold < I , Result = T > + HasInterner < Interner = I > ;
120
+
121
+ fn needs_truncation ( & mut self , interner : & I , max_size : usize , value : impl Visit < I > ) -> bool ;
122
+ }
123
+
63
124
/// A `Fulfill` is where we actually break down complex goals, instantiate
64
125
/// variables, and perform inference. It's highly stateful. It's generally used
65
126
/// in Chalk to try to solve a goal, and then package up what was learned in a
@@ -70,10 +131,10 @@ enum NegativeSolution {
70
131
/// of type inference in general. But when solving trait constraints, *fresh*
71
132
/// `Fulfill` instances will be created to solve canonicalized, free-standing
72
133
/// goals, and transport what was learned back to the outer context.
73
- pub ( crate ) struct Fulfill < ' s , ' db , I : Interner > {
134
+ pub ( crate ) struct Fulfill < ' s , ' db , I : Interner , Infer : RecursiveInferenceTable < I > > {
74
135
solver : & ' s mut Solver < ' db , I > ,
75
136
subst : Substitution < I > ,
76
- infer : InferenceTable < I > ,
137
+ infer : Infer ,
77
138
78
139
/// The remaining goals to prove or refute
79
140
obligations : Vec < Obligation < I > > ,
@@ -88,7 +149,7 @@ pub(crate) struct Fulfill<'s, 'db, I: Interner> {
88
149
cannot_prove : bool ,
89
150
}
90
151
91
- impl < ' s , ' db , I : Interner > Fulfill < ' s , ' db , I > {
152
+ impl < ' s , ' db , I : Interner > Fulfill < ' s , ' db , I , RecursiveInferenceTableImpl < I > > {
92
153
fn new < T : Fold < I , I , Result = T > + HasInterner < Interner = I > + Clone > (
93
154
solver : & ' s mut Solver < ' db , I > ,
94
155
ucanonical_goal : & UCanonical < InEnvironment < T > > ,
@@ -98,6 +159,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
98
159
ucanonical_goal. universes ,
99
160
& ucanonical_goal. canonical ,
100
161
) ;
162
+ let infer = crate :: recursive:: RecursiveInferenceTableImpl { infer } ;
101
163
let fulfill = Fulfill {
102
164
solver,
103
165
infer,
@@ -163,24 +225,20 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
163
225
// truncate to avoid overflows
164
226
match & obligation {
165
227
Obligation :: Prove ( goal) => {
166
- if truncate:: needs_truncation (
167
- self . solver . program . interner ( ) ,
168
- & mut self . infer ,
169
- 30 ,
170
- goal,
171
- ) {
228
+ if self
229
+ . infer
230
+ . needs_truncation ( self . solver . program . interner ( ) , 30 , goal)
231
+ {
172
232
// the goal is too big. Record that we should return Ambiguous
173
233
self . cannot_prove = true ;
174
234
return ;
175
235
}
176
236
}
177
237
Obligation :: Refute ( goal) => {
178
- if truncate:: needs_truncation (
179
- self . solver . program . interner ( ) ,
180
- & mut self . infer ,
181
- 30 ,
182
- goal,
183
- ) {
238
+ if self
239
+ . infer
240
+ . needs_truncation ( self . solver . program . interner ( ) , 30 , goal)
241
+ {
184
242
// the goal is too big. Record that we should return Ambiguous
185
243
self . cannot_prove = true ;
186
244
return ;
@@ -198,7 +256,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
198
256
where
199
257
T : ?Sized + Zip < I > + Debug ,
200
258
{
201
- let UnificationResult { goals, constraints } =
259
+ let ( goals, constraints) =
202
260
self . infer
203
261
. unify ( self . solver . program . interner ( ) , environment, a, b) ?;
204
262
debug ! ( "unify({:?}, {:?}) succeeded" , a, b) ;
@@ -276,15 +334,8 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
276
334
minimums : & mut Minimums ,
277
335
) -> Fallible < PositiveSolution < I > > {
278
336
let interner = self . solver . program . interner ( ) ;
279
- let Canonicalized {
280
- quantified,
281
- free_vars,
282
- ..
283
- } = self . infer . canonicalize ( interner, & wc) ;
284
- let UCanonicalized {
285
- quantified,
286
- universes,
287
- } = self . infer . u_canonicalize ( interner, & quantified) ;
337
+ let ( quantified, free_vars) = self . infer . canonicalize ( interner, & wc) ;
338
+ let ( quantified, universes) = self . infer . u_canonicalize ( interner, & quantified) ;
288
339
let result = self . solver . solve_goal ( quantified, minimums) ;
289
340
Ok ( PositiveSolution {
290
341
free_vars,
@@ -307,10 +358,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
307
358
} ;
308
359
309
360
// Negate the result
310
- let UCanonicalized {
311
- quantified,
312
- universes : _,
313
- } = self
361
+ let ( quantified, _) = self
314
362
. infer
315
363
. u_canonicalize ( self . solver . program . interner ( ) , & canonicalized) ;
316
364
let mut minimums = Minimums :: new ( ) ; // FIXME -- minimums here seems wrong
@@ -462,7 +510,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
462
510
constraints,
463
511
} ,
464
512
) ;
465
- return Ok ( Solution :: Unique ( constrained. quantified ) ) ;
513
+ return Ok ( Solution :: Unique ( constrained. 0 ) ) ;
466
514
}
467
515
468
516
// Otherwise, we have (positive or negative) obligations remaining, but
@@ -473,7 +521,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
473
521
let interner = self . solver . program . interner ( ) ;
474
522
let canonical_subst = self . infer . canonicalize ( interner, & self . subst ) ;
475
523
476
- if canonical_subst. quantified . value . is_identity_subst ( interner) {
524
+ if canonical_subst. 0 . value . is_identity_subst ( interner) {
477
525
// In this case, we didn't learn *anything* definitively. So now, we
478
526
// go one last time through the positive obligations, this time
479
527
// applying even *tentative* inference suggestions, so that we can
@@ -490,9 +538,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
490
538
} = self . prove ( & goal, minimums) . unwrap ( ) ;
491
539
if let Some ( constrained_subst) = solution. constrained_subst ( ) {
492
540
self . apply_solution ( free_vars, universes, constrained_subst) ;
493
- return Ok ( Solution :: Ambig ( Guidance :: Suggested (
494
- canonical_subst. quantified ,
495
- ) ) ) ;
541
+ return Ok ( Solution :: Ambig ( Guidance :: Suggested ( canonical_subst. 0 ) ) ) ;
496
542
}
497
543
}
498
544
}
@@ -519,9 +565,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> {
519
565
// for sure what `T` must be (it could be either `Foo<Bar>` or
520
566
// `Foo<Baz>`, but we *can* say for sure that it must be of the
521
567
// form `Foo<?0>`.
522
- Ok ( Solution :: Ambig ( Guidance :: Definite (
523
- canonical_subst. quantified ,
524
- ) ) )
568
+ Ok ( Solution :: Ambig ( Guidance :: Definite ( canonical_subst. 0 ) ) )
525
569
}
526
570
}
527
571
0 commit comments