11use rustc_hir as hir;
2- use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferCtxt } ;
2+ use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes } ;
33use rustc_infer:: traits:: { ImplSource , Obligation , PredicateObligation } ;
44use rustc_middle:: span_bug;
55use rustc_middle:: ty:: fast_reject:: DeepRejectCtxt ;
66use rustc_middle:: ty:: { self , TypingMode } ;
7+ use rustc_type_ir:: elaborate:: elaborate;
78use rustc_type_ir:: solve:: NoSolution ;
8- use thin_vec:: ThinVec ;
9+ use thin_vec:: { ThinVec , thin_vec } ;
910
1011use super :: SelectionContext ;
12+ use super :: normalize:: normalize_with_depth_to;
1113
1214pub type HostEffectObligation < ' tcx > = Obligation < ' tcx , ty:: HostEffectPredicate < ' tcx > > ;
1315
@@ -38,6 +40,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
3840 Err ( EvaluationFailure :: NoSolution ) => { }
3941 }
4042
43+ match evaluate_host_effect_from_item_bounds ( selcx, obligation) {
44+ Ok ( result) => return Ok ( result) ,
45+ Err ( EvaluationFailure :: Ambiguous ) => return Err ( EvaluationFailure :: Ambiguous ) ,
46+ Err ( EvaluationFailure :: NoSolution ) => { }
47+ }
48+
4149 match evaluate_host_effect_from_selection_candiate ( selcx, obligation) {
4250 Ok ( result) => return Ok ( result) ,
4351 Err ( EvaluationFailure :: Ambiguous ) => return Err ( EvaluationFailure :: Ambiguous ) ,
@@ -48,24 +56,45 @@ pub fn evaluate_host_effect_obligation<'tcx>(
4856}
4957
5058fn match_candidate < ' tcx > (
51- infcx : & InferCtxt < ' tcx > ,
59+ selcx : & mut SelectionContext < ' _ , ' tcx > ,
5260 obligation : & HostEffectObligation < ' tcx > ,
5361 candidate : ty:: Binder < ' tcx , ty:: HostEffectPredicate < ' tcx > > ,
62+ candidate_is_unnormalized : bool ,
63+ more_nested : impl FnOnce ( & mut SelectionContext < ' _ , ' tcx > , & mut ThinVec < PredicateObligation < ' tcx > > ) ,
5464) -> Result < ThinVec < PredicateObligation < ' tcx > > , NoSolution > {
5565 if !candidate. skip_binder ( ) . constness . satisfies ( obligation. predicate . constness ) {
5666 return Err ( NoSolution ) ;
5767 }
5868
59- let candidate = infcx. instantiate_binder_with_fresh_vars (
69+ let mut candidate = selcx . infcx . instantiate_binder_with_fresh_vars (
6070 obligation. cause . span ,
6171 BoundRegionConversionTime :: HigherRankedType ,
6272 candidate,
6373 ) ;
6474
65- let mut nested = infcx
66- . at ( & obligation. cause , obligation. param_env )
67- . eq ( DefineOpaqueTypes :: Yes , obligation. predicate . trait_ref , candidate. trait_ref ) ?
68- . into_obligations ( ) ;
75+ let mut nested = thin_vec ! [ ] ;
76+
77+ // Unlike param-env bounds, item bounds may not be normalized.
78+ if candidate_is_unnormalized {
79+ candidate = normalize_with_depth_to (
80+ selcx,
81+ obligation. param_env ,
82+ obligation. cause . clone ( ) ,
83+ obligation. recursion_depth ,
84+ candidate,
85+ & mut nested,
86+ ) ;
87+ }
88+
89+ nested. extend (
90+ selcx
91+ . infcx
92+ . at ( & obligation. cause , obligation. param_env )
93+ . eq ( DefineOpaqueTypes :: Yes , obligation. predicate . trait_ref , candidate. trait_ref ) ?
94+ . into_obligations ( ) ,
95+ ) ;
96+
97+ more_nested ( selcx, & mut nested) ;
6998
7099 for nested in & mut nested {
71100 nested. set_depth_from_parent ( obligation. recursion_depth ) ;
@@ -82,36 +111,116 @@ fn evaluate_host_effect_from_bounds<'tcx>(
82111 let drcx = DeepRejectCtxt :: relate_rigid_rigid ( selcx. tcx ( ) ) ;
83112 let mut candidate = None ;
84113
85- for predicate in obligation. param_env . caller_bounds ( ) {
86- let bound_predicate = predicate. kind ( ) ;
87- if let ty:: ClauseKind :: HostEffect ( data) = predicate. kind ( ) . skip_binder ( ) {
88- let data = bound_predicate. rebind ( data) ;
89- if data. skip_binder ( ) . trait_ref . def_id != obligation. predicate . trait_ref . def_id {
90- continue ;
114+ for clause in obligation. param_env . caller_bounds ( ) {
115+ let bound_clause = clause. kind ( ) ;
116+ let ty:: ClauseKind :: HostEffect ( data) = bound_clause. skip_binder ( ) else {
117+ continue ;
118+ } ;
119+ let data = bound_clause. rebind ( data) ;
120+ if data. skip_binder ( ) . trait_ref . def_id != obligation. predicate . trait_ref . def_id {
121+ continue ;
122+ }
123+
124+ if !drcx
125+ . args_may_unify ( obligation. predicate . trait_ref . args , data. skip_binder ( ) . trait_ref . args )
126+ {
127+ continue ;
128+ }
129+
130+ let is_match =
131+ infcx. probe ( |_| match_candidate ( selcx, obligation, data, false , |_, _| { } ) . is_ok ( ) ) ;
132+
133+ if is_match {
134+ if candidate. is_some ( ) {
135+ return Err ( EvaluationFailure :: Ambiguous ) ;
136+ } else {
137+ candidate = Some ( data) ;
91138 }
139+ }
140+ }
92141
93- if !drcx. args_may_unify (
94- obligation. predicate . trait_ref . args ,
95- data. skip_binder ( ) . trait_ref . args ,
142+ if let Some ( data) = candidate {
143+ Ok ( match_candidate ( selcx, obligation, data, false , |_, _| { } )
144+ . expect ( "candidate matched before, so it should match again" ) )
145+ } else {
146+ Err ( EvaluationFailure :: NoSolution )
147+ }
148+ }
149+
150+ fn evaluate_host_effect_from_item_bounds < ' tcx > (
151+ selcx : & mut SelectionContext < ' _ , ' tcx > ,
152+ obligation : & HostEffectObligation < ' tcx > ,
153+ ) -> Result < ThinVec < PredicateObligation < ' tcx > > , EvaluationFailure > {
154+ let infcx = selcx. infcx ;
155+ let tcx = infcx. tcx ;
156+ let drcx = DeepRejectCtxt :: relate_rigid_rigid ( selcx. tcx ( ) ) ;
157+ let mut candidate = None ;
158+
159+ let mut consider_ty = obligation. predicate . self_ty ( ) ;
160+ while let ty:: Alias ( kind @ ( ty:: Projection | ty:: Opaque ) , alias_ty) = * consider_ty. kind ( ) {
161+ if tcx. is_conditionally_const ( alias_ty. def_id ) {
162+ for clause in elaborate (
163+ tcx,
164+ tcx. explicit_implied_const_bounds ( alias_ty. def_id )
165+ . iter_instantiated_copied ( tcx, alias_ty. args )
166+ . map ( |( trait_ref, _) | {
167+ trait_ref. to_host_effect_clause ( tcx, obligation. predicate . constness )
168+ } ) ,
96169 ) {
97- continue ;
98- }
170+ let bound_clause = clause. kind ( ) ;
171+ let ty:: ClauseKind :: HostEffect ( data) = bound_clause. skip_binder ( ) else {
172+ unreachable ! ( "should not elaborate non-HostEffect from HostEffect" )
173+ } ;
174+ let data = bound_clause. rebind ( data) ;
175+ if data. skip_binder ( ) . trait_ref . def_id != obligation. predicate . trait_ref . def_id {
176+ continue ;
177+ }
99178
100- let is_match = infcx. probe ( |_| match_candidate ( infcx, obligation, data) . is_ok ( ) ) ;
179+ if !drcx. args_may_unify (
180+ obligation. predicate . trait_ref . args ,
181+ data. skip_binder ( ) . trait_ref . args ,
182+ ) {
183+ continue ;
184+ }
101185
102- if is_match {
103- if candidate. is_some ( ) {
104- return Err ( EvaluationFailure :: Ambiguous ) ;
105- } else {
106- candidate = Some ( data) ;
186+ let is_match = infcx
187+ . probe ( |_| match_candidate ( selcx, obligation, data, true , |_, _| { } ) . is_ok ( ) ) ;
188+
189+ if is_match {
190+ if candidate. is_some ( ) {
191+ return Err ( EvaluationFailure :: Ambiguous ) ;
192+ } else {
193+ candidate = Some ( ( data, alias_ty) ) ;
194+ }
107195 }
108196 }
109197 }
198+
199+ if kind != ty:: Projection {
200+ break ;
201+ }
202+
203+ consider_ty = alias_ty. self_ty ( ) ;
110204 }
111205
112- if let Some ( data) = candidate {
113- Ok ( match_candidate ( infcx, obligation, data)
114- . expect ( "candidate matched before, so it should match again" ) )
206+ if let Some ( ( data, alias_ty) ) = candidate {
207+ Ok ( match_candidate ( selcx, obligation, data, true , |selcx, nested| {
208+ // An alias bound only holds if we also check the const conditions
209+ // of the alias, so we need to register those, too.
210+ let const_conditions = normalize_with_depth_to (
211+ selcx,
212+ obligation. param_env ,
213+ obligation. cause . clone ( ) ,
214+ obligation. recursion_depth ,
215+ tcx. const_conditions ( alias_ty. def_id ) . instantiate ( tcx, alias_ty. args ) ,
216+ nested,
217+ ) ;
218+ nested. extend ( const_conditions. into_iter ( ) . map ( |( trait_ref, _) | {
219+ obligation
220+ . with ( tcx, trait_ref. to_host_effect_clause ( tcx, obligation. predicate . constness ) )
221+ } ) ) ;
222+ } )
223+ . expect ( "candidate matched before, so it should match again" ) )
115224 } else {
116225 Err ( EvaluationFailure :: NoSolution )
117226 }
0 commit comments