@@ -13,19 +13,38 @@ use tracing::{debug, instrument, trace};
1313
1414use crate :: FnCtxt ;
1515
16+ /// Whatever to use subtyping or not when inspecting obligations
17+ #[ derive( Debug , Copy , Clone ) ]
18+ pub ( crate ) enum UseSubtyping {
19+ /// Do **not** use subtyping. [`FnCtxt::obligations_for_self_ty`] will only return obligations
20+ /// where the self type is known to be equal to the provided vid.
21+ No ,
22+
23+ /// Use subtyping. [`FnCtxt::obligations_for_self_ty`] will return obligations
24+ /// where the self type is related to the provided vid via subtyping.
25+ ///
26+ /// Using this requires extra care, as traits holding for a subtype or a supertype, does not
27+ /// necessarily imply that they hold for the respective supertype or subtype.
28+ Yes ,
29+ }
30+
1631impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
1732 /// Returns a list of all obligations whose self type has been unified
1833 /// with the unconstrained type `self_ty`.
1934 #[ instrument( skip( self ) , level = "debug" ) ]
20- pub ( crate ) fn obligations_for_self_ty ( & self , self_ty : ty:: TyVid ) -> PredicateObligations < ' tcx > {
35+ pub ( crate ) fn obligations_for_self_ty (
36+ & self ,
37+ self_ty : ty:: TyVid ,
38+ subtyping : UseSubtyping ,
39+ ) -> PredicateObligations < ' tcx > {
2140 if self . next_trait_solver ( ) {
22- self . obligations_for_self_ty_next ( self_ty)
41+ self . obligations_for_self_ty_next ( self_ty, subtyping )
2342 } else {
24- let ty_var_root = self . root_var ( self_ty) ;
2543 let mut obligations = self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ;
2644 trace ! ( "pending_obligations = {:#?}" , obligations) ;
27- obligations
28- . retain ( |obligation| self . predicate_has_self_ty ( obligation. predicate , ty_var_root) ) ;
45+ obligations. retain ( |obligation| {
46+ self . predicate_has_self_ty ( obligation. predicate , self_ty, subtyping)
47+ } ) ;
2948 obligations
3049 }
3150 }
@@ -35,14 +54,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3554 & self ,
3655 predicate : ty:: Predicate < ' tcx > ,
3756 expected_vid : ty:: TyVid ,
57+ subtyping : UseSubtyping ,
3858 ) -> bool {
3959 match predicate. kind ( ) . skip_binder ( ) {
4060 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( data) ) => {
41- self . type_matches_expected_vid ( data. self_ty ( ) , expected_vid)
61+ self . type_matches_expected_vid ( data. self_ty ( ) , expected_vid, subtyping )
4262 }
4363 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( data) ) => {
4464 if data. projection_term . kind . is_trait_projection ( ) {
45- self . type_matches_expected_vid ( data. self_ty ( ) , expected_vid)
65+ self . type_matches_expected_vid ( data. self_ty ( ) , expected_vid, subtyping )
4666 } else {
4767 false
4868 }
@@ -64,21 +84,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6484 }
6585
6686 #[ instrument( level = "debug" , skip( self ) , ret) ]
67- fn type_matches_expected_vid ( & self , ty : Ty < ' tcx > , expected_vid : ty:: TyVid ) -> bool {
87+ fn type_matches_expected_vid (
88+ & self ,
89+ ty : Ty < ' tcx > ,
90+ expected_vid : ty:: TyVid ,
91+ subtyping : UseSubtyping ,
92+ ) -> bool {
6893 let ty = self . shallow_resolve ( ty) ;
6994 debug ! ( ?ty) ;
7095
7196 match * ty. kind ( ) {
72- ty:: Infer ( ty:: TyVar ( found_vid) ) => {
73- self . root_var ( expected_vid) == self . root_var ( found_vid)
74- }
97+ ty:: Infer ( ty:: TyVar ( found_vid) ) => match subtyping {
98+ UseSubtyping :: No => self . root_var ( expected_vid) == self . root_var ( found_vid) ,
99+ UseSubtyping :: Yes => {
100+ self . sub_unification_table_root_var ( expected_vid)
101+ == self . sub_unification_table_root_var ( found_vid)
102+ }
103+ } ,
75104 _ => false ,
76105 }
77106 }
78107
79108 pub ( crate ) fn obligations_for_self_ty_next (
80109 & self ,
81110 self_ty : ty:: TyVid ,
111+ subtyping : UseSubtyping ,
82112 ) -> PredicateObligations < ' tcx > {
83113 // We only look at obligations which may reference the self type.
84114 // This lookup uses the `sub_root` instead of the inference variable
@@ -93,13 +123,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
93123 . borrow ( )
94124 . pending_obligations_potentially_referencing_sub_root ( & self . infcx , sub_root_var) ;
95125 debug ! ( ?obligations) ;
126+
96127 let mut obligations_for_self_ty = PredicateObligations :: new ( ) ;
97128 for obligation in obligations {
98129 let mut visitor = NestedObligationsForSelfTy {
99130 fcx : self ,
100131 self_ty,
101132 obligations_for_self_ty : & mut obligations_for_self_ty,
102133 root_cause : & obligation. cause ,
134+ subtyping,
103135 } ;
104136
105137 let goal = obligation. as_goal ( ) ;
@@ -182,6 +214,7 @@ struct NestedObligationsForSelfTy<'a, 'tcx> {
182214 self_ty : ty:: TyVid ,
183215 root_cause : & ' a ObligationCause < ' tcx > ,
184216 obligations_for_self_ty : & ' a mut PredicateObligations < ' tcx > ,
217+ subtyping : UseSubtyping ,
185218}
186219
187220impl < ' tcx > ProofTreeVisitor < ' tcx > for NestedObligationsForSelfTy < ' _ , ' tcx > {
@@ -209,15 +242,15 @@ impl<'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'_, 'tcx> {
209242 . orig_values ( )
210243 . iter ( )
211244 . filter_map ( |arg| arg. as_type ( ) )
212- . any ( |ty| self . fcx . type_matches_expected_vid ( ty, self . self_ty ) )
245+ . any ( |ty| self . fcx . type_matches_expected_vid ( ty, self . self_ty , self . subtyping ) )
213246 {
214247 debug ! ( goal = ?inspect_goal. goal( ) , "goal does not mention self type" ) ;
215248 return ;
216249 }
217250
218251 let tcx = self . fcx . tcx ;
219252 let goal = inspect_goal. goal ( ) ;
220- if self . fcx . predicate_has_self_ty ( goal. predicate , self . self_ty ) {
253+ if self . fcx . predicate_has_self_ty ( goal. predicate , self . self_ty , self . subtyping ) {
221254 self . obligations_for_self_ty . push ( traits:: Obligation :: new (
222255 tcx,
223256 self . root_cause . clone ( ) ,
0 commit comments