1919
2020use std:: mem;
2121
22+ use rustc_hir:: def_id:: DefId ;
2223use rustc_infer:: infer:: canonical:: { Canonical , CanonicalVarKind , CanonicalVarValues } ;
2324use rustc_infer:: infer:: canonical:: { OriginalQueryValues , QueryRegionConstraints , QueryResponse } ;
2425use rustc_infer:: infer:: { InferCtxt , InferOk , TyCtxtInferExt } ;
2526use rustc_infer:: traits:: query:: NoSolution ;
2627use rustc_infer:: traits:: Obligation ;
2728use rustc_middle:: infer:: canonical:: Certainty as OldCertainty ;
2829use 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+ } ;
3033use rustc_span:: DUMMY_SP ;
3134
3235use crate :: traits:: ObligationCause ;
@@ -87,6 +90,8 @@ pub enum Certainty {
8790}
8891
8992impl Certainty {
93+ pub const AMBIGUOUS : Certainty = Certainty :: Maybe ( MaybeCause :: Ambiguity ) ;
94+
9095 /// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
9196 /// use this function to unify the certainty of these goals
9297 pub fn unify_and ( self , other : Certainty ) -> Certainty {
@@ -243,16 +248,28 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
243248 ty:: PredicateKind :: Clause ( ty:: Clause :: RegionOutlives ( predicate) ) => {
244249 self . compute_region_outlives_goal ( Goal { param_env, predicate } )
245250 }
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 ) ,
246263 // FIXME: implement these predicates :)
247264 ty:: PredicateKind :: WellFormed ( _)
248265 | ty:: PredicateKind :: ObjectSafe ( _)
249- | ty:: PredicateKind :: ClosureKind ( _, _, _)
250- | ty:: PredicateKind :: Subtype ( _)
251- | ty:: PredicateKind :: Coerce ( _)
252266 | 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+ }
256273 }
257274 } else {
258275 let kind = self . infcx . replace_bound_vars_with_placeholders ( kind) ;
@@ -275,6 +292,58 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
275292 ) -> QueryResult < ' tcx > {
276293 self . make_canonical_response ( Certainty :: Yes )
277294 }
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+ }
278347}
279348
280349impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
0 commit comments