19
19
20
20
use std:: mem;
21
21
22
+ use rustc_hir:: def_id:: DefId ;
22
23
use rustc_infer:: infer:: canonical:: { Canonical , CanonicalVarKind , CanonicalVarValues } ;
23
24
use rustc_infer:: infer:: canonical:: { OriginalQueryValues , QueryRegionConstraints , QueryResponse } ;
24
25
use rustc_infer:: infer:: { InferCtxt , InferOk , TyCtxtInferExt } ;
25
26
use rustc_infer:: traits:: query:: NoSolution ;
26
27
use rustc_infer:: traits:: Obligation ;
27
28
use rustc_middle:: infer:: canonical:: Certainty as OldCertainty ;
28
29
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
29
- use rustc_middle:: ty:: { RegionOutlivesPredicate , ToPredicate , TypeOutlivesPredicate } ;
30
+ use rustc_middle:: ty:: {
31
+ CoercePredicate , RegionOutlivesPredicate , SubtypePredicate , ToPredicate , TypeOutlivesPredicate ,
32
+ } ;
30
33
use rustc_span:: DUMMY_SP ;
31
34
32
35
use crate :: traits:: ObligationCause ;
@@ -87,6 +90,8 @@ pub enum Certainty {
87
90
}
88
91
89
92
impl Certainty {
93
+ pub const AMBIGUOUS : Certainty = Certainty :: Maybe ( MaybeCause :: Ambiguity ) ;
94
+
90
95
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
91
96
/// use this function to unify the certainty of these goals
92
97
pub fn unify_and ( self , other : Certainty ) -> Certainty {
@@ -243,16 +248,28 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
243
248
ty:: PredicateKind :: Clause ( ty:: Clause :: RegionOutlives ( predicate) ) => {
244
249
self . compute_region_outlives_goal ( Goal { param_env, predicate } )
245
250
}
251
+ ty:: PredicateKind :: Subtype ( predicate) => {
252
+ self . compute_subtype_goal ( Goal { param_env, predicate } )
253
+ }
254
+ ty:: PredicateKind :: Coerce ( predicate) => {
255
+ self . compute_coerce_goal ( Goal { param_env, predicate } )
256
+ }
257
+ ty:: PredicateKind :: ClosureKind ( def_id, substs, kind) => self
258
+ . compute_closure_kind_goal ( Goal {
259
+ param_env,
260
+ predicate : ( def_id, substs, kind) ,
261
+ } ) ,
262
+ ty:: PredicateKind :: Ambiguous => self . make_canonical_response ( Certainty :: AMBIGUOUS ) ,
246
263
// FIXME: implement these predicates :)
247
264
ty:: PredicateKind :: WellFormed ( _)
248
265
| ty:: PredicateKind :: ObjectSafe ( _)
249
- | ty:: PredicateKind :: ClosureKind ( _, _, _)
250
- | ty:: PredicateKind :: Subtype ( _)
251
- | ty:: PredicateKind :: Coerce ( _)
252
266
| ty:: PredicateKind :: ConstEvaluatable ( _)
253
- | ty:: PredicateKind :: ConstEquate ( _, _)
254
- | ty:: PredicateKind :: TypeWellFormedFromEnv ( _)
255
- | ty:: PredicateKind :: Ambiguous => self . make_canonical_response ( Certainty :: Yes ) ,
267
+ | ty:: PredicateKind :: ConstEquate ( _, _) => {
268
+ self . make_canonical_response ( Certainty :: Yes )
269
+ }
270
+ ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => {
271
+ bug ! ( "TypeWellFormedFromEnv is only used for Chalk" )
272
+ }
256
273
}
257
274
} else {
258
275
let kind = self . infcx . replace_bound_vars_with_placeholders ( kind) ;
@@ -275,6 +292,58 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
275
292
) -> QueryResult < ' tcx > {
276
293
self . make_canonical_response ( Certainty :: Yes )
277
294
}
295
+
296
+ fn compute_coerce_goal (
297
+ & mut self ,
298
+ goal : Goal < ' tcx , CoercePredicate < ' tcx > > ,
299
+ ) -> QueryResult < ' tcx > {
300
+ self . compute_subtype_goal ( Goal {
301
+ param_env : goal. param_env ,
302
+ predicate : SubtypePredicate {
303
+ a_is_expected : false ,
304
+ a : goal. predicate . a ,
305
+ b : goal. predicate . b ,
306
+ } ,
307
+ } )
308
+ }
309
+
310
+ fn compute_subtype_goal (
311
+ & mut self ,
312
+ goal : Goal < ' tcx , SubtypePredicate < ' tcx > > ,
313
+ ) -> QueryResult < ' tcx > {
314
+ if goal. predicate . a . is_ty_var ( ) && goal. predicate . b . is_ty_var ( ) {
315
+ // FIXME: Do we want to register a subtype relation between these vars?
316
+ // That won't actually reflect in the query response, so it seems moot.
317
+ self . make_canonical_response ( Certainty :: AMBIGUOUS )
318
+ } else {
319
+ self . infcx . probe ( |_| {
320
+ let InferOk { value : ( ) , obligations } = self
321
+ . infcx
322
+ . at ( & ObligationCause :: dummy ( ) , goal. param_env )
323
+ . sub ( goal. predicate . a , goal. predicate . b ) ?;
324
+ self . evaluate_all_and_make_canonical_response (
325
+ obligations. into_iter ( ) . map ( |pred| pred. into ( ) ) . collect ( ) ,
326
+ )
327
+ } )
328
+ }
329
+ }
330
+
331
+ fn compute_closure_kind_goal (
332
+ & mut self ,
333
+ goal : Goal < ' tcx , ( DefId , ty:: SubstsRef < ' tcx > , ty:: ClosureKind ) > ,
334
+ ) -> QueryResult < ' tcx > {
335
+ let ( _, substs, expected_kind) = goal. predicate ;
336
+ let found_kind = substs. as_closure ( ) . kind_ty ( ) . to_opt_closure_kind ( ) ;
337
+
338
+ let Some ( found_kind) = found_kind else {
339
+ return self . make_canonical_response ( Certainty :: AMBIGUOUS ) ;
340
+ } ;
341
+ if found_kind. extends ( expected_kind) {
342
+ self . make_canonical_response ( Certainty :: Yes )
343
+ } else {
344
+ Err ( NoSolution )
345
+ }
346
+ }
278
347
}
279
348
280
349
impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
0 commit comments