@@ -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,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
298311 }
299312
300313 fn visit_goal ( & mut self , goal : & super :: inspect:: InspectGoal < ' _ , ' tcx > ) -> Self :: Result {
314+ // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
315+ // This most likely means that the goal just didn't unify at all, e.g. a param
316+ // candidate with an alias in it.
301317 let candidates = goal. candidates ( ) ;
302- // 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- }
308318
309319 let [ candidate] = candidates. as_slice ( ) else {
310320 return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
@@ -320,80 +330,71 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
320330 let tcx = goal. infcx ( ) . tcx ;
321331 let mut impl_where_bound_count = 0 ;
322332 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 ;
333+ let obligation;
334+ match nested_goal. source ( ) {
335+ GoalSource :: Misc => {
336+ continue ;
337+ }
338+ GoalSource :: ImplWhereBound => {
339+ obligation = Obligation {
340+ cause : derive_cause (
341+ tcx,
342+ candidate. kind ( ) ,
343+ self . obligation . cause . clone ( ) ,
344+ impl_where_bound_count,
345+ parent_trait_pred,
346+ ) ,
347+ param_env : nested_goal. goal ( ) . param_env ,
348+ predicate : nested_goal. goal ( ) . predicate ,
349+ recursion_depth : self . obligation . recursion_depth + 1 ,
350+ } ;
351+ impl_where_bound_count += 1 ;
352+ }
353+ GoalSource :: InstantiateHigherRanked => {
354+ obligation = self . obligation . clone ( ) ;
355+ }
327356 }
328357
329358 // Skip nested goals that hold.
359+ //FIXME: We should change the max allowed certainty based on if we're
360+ // visiting an ambiguity or error obligation.
330361 if matches ! ( nested_goal. result( ) , Ok ( Certainty :: Yes ) ) {
331362 continue ;
332363 }
333364
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- ) ?;
365+ self . with_derived_obligation ( obligation, |this| nested_goal. visit_with ( this) ) ?;
381366 }
382367
383368 ControlFlow :: Break ( self . obligation . clone ( ) )
384369 }
385370}
386371
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)
372+ fn derive_cause < ' tcx > (
373+ tcx : TyCtxt < ' tcx > ,
374+ candidate_kind : ProbeKind < ' tcx > ,
375+ mut cause : ObligationCause < ' tcx > ,
376+ idx : usize ,
377+ parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
378+ ) -> ObligationCause < ' tcx > {
379+ match candidate_kind {
380+ ProbeKind :: TraitCandidate { source : CandidateSource :: Impl ( impl_def_id) , result : _ } => {
381+ if let Some ( ( _, span) ) =
382+ tcx. predicates_of ( impl_def_id) . instantiate_identity ( tcx) . iter ( ) . nth ( idx)
383+ {
384+ cause = cause. derived_cause ( parent_trait_pred, |derived| {
385+ traits:: ImplDerivedObligation ( Box :: new ( traits:: ImplDerivedObligationCause {
386+ derived,
387+ impl_or_alias_def_id : impl_def_id,
388+ impl_def_predicate_index : Some ( idx) ,
389+ span,
390+ } ) )
391+ } )
392+ }
393+ }
394+ ProbeKind :: TraitCandidate { source : CandidateSource :: BuiltinImpl ( ..) , result : _ } => {
395+ cause = cause. derived_cause ( parent_trait_pred, traits:: BuiltinDerivedObligation ) ;
396+ }
397+ _ => { }
398+ } ;
399+ cause
399400}
0 commit comments