@@ -7,10 +7,10 @@ use rustc_infer::traits::solve::inspect::ProbeKind;
77use rustc_infer:: traits:: solve:: { CandidateSource , GoalSource , MaybeCause } ;
88use rustc_infer:: traits:: {
99 self , FulfillmentError , FulfillmentErrorCode , MismatchedProjectionTypes , Obligation ,
10- PredicateObligation , SelectionError , TraitEngine ,
10+ ObligationCause , PredicateObligation , SelectionError , TraitEngine ,
1111} ;
12- use rustc_middle:: ty;
1312use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
13+ use rustc_middle:: ty:: { self , TyCtxt } ;
1414
1515use super :: eval_ctxt:: GenerateProofTree ;
1616use super :: inspect:: { ProofTreeInferCtxtExt , ProofTreeVisitor } ;
@@ -219,14 +219,14 @@ fn fulfillment_error_for_no_solution<'tcx>(
219219 }
220220 ty:: PredicateKind :: Subtype ( pred) => {
221221 let ( a, b) = infcx. enter_forall_and_leak_universe (
222- root_obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
222+ obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
223223 ) ;
224224 let expected_found = ExpectedFound :: new ( true , a, b) ;
225225 FulfillmentErrorCode :: SubtypeError ( expected_found, TypeError :: Sorts ( expected_found) )
226226 }
227227 ty:: PredicateKind :: Coerce ( pred) => {
228228 let ( a, b) = infcx. enter_forall_and_leak_universe (
229- root_obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
229+ obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
230230 ) ;
231231 let expected_found = ExpectedFound :: new ( false , a, b) ;
232232 FulfillmentErrorCode :: SubtypeError ( expected_found, TypeError :: Sorts ( expected_found) )
@@ -272,17 +272,30 @@ fn fulfillment_error_for_stalled<'tcx>(
272272 }
273273}
274274
275+ fn find_best_leaf_obligation < ' tcx > (
276+ infcx : & InferCtxt < ' tcx > ,
277+ obligation : & PredicateObligation < ' tcx > ,
278+ ) -> PredicateObligation < ' tcx > {
279+ let obligation = infcx. resolve_vars_if_possible ( obligation. clone ( ) ) ;
280+ infcx
281+ . visit_proof_tree (
282+ obligation. clone ( ) . into ( ) ,
283+ & mut BestObligation { obligation : obligation. clone ( ) } ,
284+ )
285+ . break_value ( )
286+ . unwrap_or ( obligation)
287+ }
288+
275289struct BestObligation < ' tcx > {
276290 obligation : PredicateObligation < ' tcx > ,
277291}
278292
279293impl < ' tcx > BestObligation < ' tcx > {
280294 fn with_derived_obligation (
281295 & mut self ,
282- derive_obligation : impl FnOnce ( & mut Self ) -> PredicateObligation < ' tcx > ,
296+ derived_obligation : PredicateObligation < ' tcx > ,
283297 and_then : impl FnOnce ( & mut Self ) -> <Self as ProofTreeVisitor < ' tcx > >:: Result ,
284298 ) -> <Self as ProofTreeVisitor < ' tcx > >:: Result {
285- let derived_obligation = derive_obligation ( self ) ;
286299 let old_obligation = std:: mem:: replace ( & mut self . obligation , derived_obligation) ;
287300 let res = and_then ( self ) ;
288301 self . obligation = old_obligation;
@@ -298,13 +311,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
298311 }
299312
300313 fn visit_goal ( & mut self , goal : & super :: inspect:: InspectGoal < ' _ , ' tcx > ) -> Self :: Result {
301- let candidates = goal. candidates ( ) ;
302314 // FIXME: Throw out candidates that have no failing WC and >1 failing misc goal.
303-
304- // HACK:
305- if self . obligation . recursion_depth > 3 {
306- return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
307- }
315+ let candidates = goal. candidates ( ) ;
308316
309317 let [ candidate] = candidates. as_slice ( ) else {
310318 return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
@@ -320,80 +328,71 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
320328 let tcx = goal. infcx ( ) . tcx ;
321329 let mut impl_where_bound_count = 0 ;
322330 for nested_goal in candidate. instantiate_nested_goals ( self . span ( ) ) {
323- if matches ! ( nested_goal. source( ) , GoalSource :: ImplWhereBound ) {
324- impl_where_bound_count += 1 ;
325- } else {
326- continue ;
331+ let obligation;
332+ match nested_goal. source ( ) {
333+ GoalSource :: Misc => {
334+ continue ;
335+ }
336+ GoalSource :: ImplWhereBound => {
337+ obligation = Obligation {
338+ cause : derive_cause (
339+ tcx,
340+ candidate. kind ( ) ,
341+ self . obligation . cause . clone ( ) ,
342+ impl_where_bound_count,
343+ parent_trait_pred,
344+ ) ,
345+ param_env : nested_goal. goal ( ) . param_env ,
346+ predicate : nested_goal. goal ( ) . predicate ,
347+ recursion_depth : self . obligation . recursion_depth + 1 ,
348+ } ;
349+ impl_where_bound_count += 1 ;
350+ }
351+ GoalSource :: InstantiateHigherRanked => {
352+ obligation = self . obligation . clone ( ) ;
353+ }
327354 }
328355
329356 // Skip nested goals that hold.
357+ //FIXME: We should change the max allowed certainty based on if we're
358+ // visiting an ambiguity or error obligation.
330359 if matches ! ( nested_goal. result( ) , Ok ( Certainty :: Yes ) ) {
331360 continue ;
332361 }
333362
334- self . with_derived_obligation (
335- |self_| {
336- let mut cause = self_. obligation . cause . clone ( ) ;
337- cause = match candidate. kind ( ) {
338- ProbeKind :: TraitCandidate {
339- source : CandidateSource :: Impl ( impl_def_id) ,
340- result : _,
341- } => {
342- let idx = impl_where_bound_count - 1 ;
343- if let Some ( ( _, span) ) = tcx
344- . predicates_of ( impl_def_id)
345- . instantiate_identity ( tcx)
346- . iter ( )
347- . nth ( idx)
348- {
349- cause. derived_cause ( parent_trait_pred, |derived| {
350- traits:: ImplDerivedObligation ( Box :: new (
351- traits:: ImplDerivedObligationCause {
352- derived,
353- impl_or_alias_def_id : impl_def_id,
354- impl_def_predicate_index : Some ( idx) ,
355- span,
356- } ,
357- ) )
358- } )
359- } else {
360- cause
361- }
362- }
363- ProbeKind :: TraitCandidate {
364- source : CandidateSource :: BuiltinImpl ( ..) ,
365- result : _,
366- } => {
367- cause. derived_cause ( parent_trait_pred, traits:: BuiltinDerivedObligation )
368- }
369- _ => cause,
370- } ;
371-
372- Obligation {
373- cause,
374- param_env : nested_goal. goal ( ) . param_env ,
375- predicate : nested_goal. goal ( ) . predicate ,
376- recursion_depth : self_. obligation . recursion_depth + 1 ,
377- }
378- } ,
379- |self_| self_. visit_goal ( & nested_goal) ,
380- ) ?;
363+ self . with_derived_obligation ( obligation, |self_| nested_goal. visit_with ( self_) ) ?;
381364 }
382365
383366 ControlFlow :: Break ( self . obligation . clone ( ) )
384367 }
385368}
386369
387- fn find_best_leaf_obligation < ' tcx > (
388- infcx : & InferCtxt < ' tcx > ,
389- obligation : & PredicateObligation < ' tcx > ,
390- ) -> PredicateObligation < ' tcx > {
391- let obligation = infcx. resolve_vars_if_possible ( obligation. clone ( ) ) ;
392- infcx
393- . visit_proof_tree (
394- obligation. clone ( ) . into ( ) ,
395- & mut BestObligation { obligation : obligation. clone ( ) } ,
396- )
397- . break_value ( )
398- . unwrap_or ( obligation)
370+ fn derive_cause < ' tcx > (
371+ tcx : TyCtxt < ' tcx > ,
372+ candidate_kind : ProbeKind < ' tcx > ,
373+ mut cause : ObligationCause < ' tcx > ,
374+ idx : usize ,
375+ parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
376+ ) -> ObligationCause < ' tcx > {
377+ match candidate_kind {
378+ ProbeKind :: TraitCandidate { source : CandidateSource :: Impl ( impl_def_id) , result : _ } => {
379+ if let Some ( ( _, span) ) =
380+ tcx. predicates_of ( impl_def_id) . instantiate_identity ( tcx) . iter ( ) . nth ( idx)
381+ {
382+ cause = cause. derived_cause ( parent_trait_pred, |derived| {
383+ traits:: ImplDerivedObligation ( Box :: new ( traits:: ImplDerivedObligationCause {
384+ derived,
385+ impl_or_alias_def_id : impl_def_id,
386+ impl_def_predicate_index : Some ( idx) ,
387+ span,
388+ } ) )
389+ } )
390+ }
391+ }
392+ ProbeKind :: TraitCandidate { source : CandidateSource :: BuiltinImpl ( ..) , result : _ } => {
393+ cause = cause. derived_cause ( parent_trait_pred, traits:: BuiltinDerivedObligation ) ;
394+ }
395+ _ => { }
396+ } ;
397+ cause
399398}
0 commit comments