@@ -29,6 +29,7 @@ use crate::infer::outlives::env::OutlivesEnvironment;
2929use crate :: infer:: InferOk ;
3030use crate :: solve:: inspect:: { InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor } ;
3131use crate :: solve:: { deeply_normalize_for_diagnostics, inspect} ;
32+ use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt ;
3233use crate :: traits:: select:: IntercrateAmbiguityCause ;
3334use crate :: traits:: {
3435 util, FulfillmentErrorCode , NormalizeExt , Obligation , ObligationCause , PredicateObligation ,
@@ -624,14 +625,13 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
624625 // at ambiguous goals, as for others the coherence unknowable candidate
625626 // was irrelevant.
626627 match goal. result ( ) {
627- Ok ( Certainty :: Maybe ( _) ) => { }
628628 Ok ( Certainty :: Yes ) | Err ( NoSolution ) => return ,
629+ Ok ( Certainty :: Maybe ( _) ) => { }
629630 }
630631
631- let Goal { param_env, predicate } = goal. goal ( ) ;
632-
633632 // For bound predicates we simply call `infcx.enter_forall`
634633 // and then prove the resulting predicate as a nested goal.
634+ let Goal { param_env, predicate } = goal. goal ( ) ;
635635 let trait_ref = match predicate. kind ( ) . no_bound_vars ( ) {
636636 Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( tr) ) ) => tr. trait_ref ,
637637 Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( proj) ) )
@@ -645,7 +645,11 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
645645 _ => return ,
646646 } ;
647647
648- // Add ambiguity causes for reservation impls.
648+ if trait_ref. references_error ( ) {
649+ return ;
650+ }
651+
652+ let mut candidates = goal. candidates ( ) ;
649653 for cand in goal. candidates ( ) {
650654 if let inspect:: ProbeKind :: TraitCandidate {
651655 source : CandidateSource :: Impl ( def_id) ,
@@ -664,78 +668,68 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
664668 }
665669 }
666670
667- // Add ambiguity causes for unknowable goals.
668- let mut ambiguity_cause = None ;
669- for cand in goal. candidates ( ) {
670- if let inspect:: ProbeKind :: TraitCandidate {
671- source : CandidateSource :: CoherenceUnknowable ,
672- result : Ok ( _) ,
673- } = cand. kind ( )
674- {
675- let lazily_normalize_ty = |mut ty : Ty < ' tcx > | {
676- if matches ! ( ty. kind( ) , ty:: Alias ( ..) ) {
677- let ocx = ObligationCtxt :: new ( infcx) ;
678- ty = ocx
679- . structurally_normalize ( & ObligationCause :: dummy ( ) , param_env, ty)
680- . map_err ( |_| ( ) ) ?;
681- if !ocx. select_where_possible ( ) . is_empty ( ) {
682- return Err ( ( ) ) ;
683- }
684- }
685- Ok ( ty)
686- } ;
671+ // We also look for unknowable candidates. In case a goal is unknowable, there's
672+ // always exactly 1 candidate.
673+ let Some ( cand) = candidates. pop ( ) else {
674+ return ;
675+ } ;
687676
688- infcx. probe ( |_| {
689- match trait_ref_is_knowable ( infcx, trait_ref, lazily_normalize_ty) {
690- Err ( ( ) ) => { }
691- Ok ( Ok ( ( ) ) ) => warn ! ( "expected an unknowable trait ref: {trait_ref:?}" ) ,
692- Ok ( Err ( conflict) ) => {
693- if !trait_ref. references_error ( ) {
694- // Normalize the trait ref for diagnostics, ignoring any errors if this fails.
695- let trait_ref =
696- deeply_normalize_for_diagnostics ( infcx, param_env, trait_ref) ;
697-
698- let self_ty = trait_ref. self_ty ( ) ;
699- let self_ty = self_ty. has_concrete_skeleton ( ) . then ( || self_ty) ;
700- ambiguity_cause = Some ( match conflict {
701- Conflict :: Upstream => {
702- IntercrateAmbiguityCause :: UpstreamCrateUpdate {
703- trait_ref,
704- self_ty,
705- }
706- }
707- Conflict :: Downstream => {
708- IntercrateAmbiguityCause :: DownstreamCrate {
709- trait_ref,
710- self_ty,
711- }
712- }
713- } ) ;
714- }
715- }
716- }
717- } )
718- } else {
719- match cand. result ( ) {
720- // We only add an ambiguity cause if the goal would otherwise
721- // result in an error.
722- //
723- // FIXME: While this matches the behavior of the
724- // old solver, it is not the only way in which the unknowable
725- // candidates *weaken* coherence, they can also force otherwise
726- // successful normalization to be ambiguous.
727- Ok ( Certainty :: Maybe ( _) | Certainty :: Yes ) => {
728- ambiguity_cause = None ;
729- break ;
730- }
731- Err ( NoSolution ) => continue ,
677+ let inspect:: ProbeKind :: TraitCandidate {
678+ source : CandidateSource :: CoherenceUnknowable ,
679+ result : Ok ( _) ,
680+ } = cand. kind ( )
681+ else {
682+ return ;
683+ } ;
684+
685+ let lazily_normalize_ty = |mut ty : Ty < ' tcx > | {
686+ if matches ! ( ty. kind( ) , ty:: Alias ( ..) ) {
687+ let ocx = ObligationCtxt :: new ( infcx) ;
688+ ty = ocx
689+ . structurally_normalize ( & ObligationCause :: dummy ( ) , param_env, ty)
690+ . map_err ( |_| ( ) ) ?;
691+ if !ocx. select_where_possible ( ) . is_empty ( ) {
692+ return Err ( ( ) ) ;
732693 }
733694 }
734- }
695+ Ok ( ty)
696+ } ;
735697
736- if let Some ( ambiguity_cause) = ambiguity_cause {
737- self . causes . insert ( ambiguity_cause) ;
738- }
698+ infcx. probe ( |_| {
699+ let conflict = match trait_ref_is_knowable ( infcx, trait_ref, lazily_normalize_ty) {
700+ Err ( ( ) ) => return ,
701+ Ok ( Ok ( ( ) ) ) => {
702+ warn ! ( "expected an unknowable trait ref: {trait_ref:?}" ) ;
703+ return ;
704+ }
705+ Ok ( Err ( conflict) ) => conflict,
706+ } ;
707+
708+ // It is only relevant that a goal is unknowable if it would have otherwise
709+ // failed.
710+ let non_intercrate_infcx = infcx. fork_with_intercrate ( false ) ;
711+ if non_intercrate_infcx. predicate_may_hold ( & Obligation :: new (
712+ infcx. tcx ,
713+ ObligationCause :: dummy ( ) ,
714+ param_env,
715+ predicate,
716+ ) ) {
717+ return ;
718+ }
719+
720+ // Normalize the trait ref for diagnostics, ignoring any errors if this fails.
721+ let trait_ref = deeply_normalize_for_diagnostics ( infcx, param_env, trait_ref) ;
722+ let self_ty = trait_ref. self_ty ( ) ;
723+ let self_ty = self_ty. has_concrete_skeleton ( ) . then ( || self_ty) ;
724+ self . causes . insert ( match conflict {
725+ Conflict :: Upstream => {
726+ IntercrateAmbiguityCause :: UpstreamCrateUpdate { trait_ref, self_ty }
727+ }
728+ Conflict :: Downstream => {
729+ IntercrateAmbiguityCause :: DownstreamCrate { trait_ref, self_ty }
730+ }
731+ } ) ;
732+ } ) ;
739733 }
740734}
741735
0 commit comments