@@ -29,6 +29,7 @@ use crate::infer::outlives::env::OutlivesEnvironment;
29
29
use crate :: infer:: InferOk ;
30
30
use crate :: solve:: inspect:: { InspectGoal , ProofTreeInferCtxtExt , ProofTreeVisitor } ;
31
31
use crate :: solve:: { deeply_normalize_for_diagnostics, inspect} ;
32
+ use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt ;
32
33
use crate :: traits:: select:: IntercrateAmbiguityCause ;
33
34
use crate :: traits:: {
34
35
util, FulfillmentErrorCode , NormalizeExt , Obligation , ObligationCause , PredicateObligation ,
@@ -624,14 +625,13 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
624
625
// at ambiguous goals, as for others the coherence unknowable candidate
625
626
// was irrelevant.
626
627
match goal. result ( ) {
627
- Ok ( Certainty :: Maybe ( _) ) => { }
628
628
Ok ( Certainty :: Yes ) | Err ( NoSolution ) => return ,
629
+ Ok ( Certainty :: Maybe ( _) ) => { }
629
630
}
630
631
631
- let Goal { param_env, predicate } = goal. goal ( ) ;
632
-
633
632
// For bound predicates we simply call `infcx.enter_forall`
634
633
// and then prove the resulting predicate as a nested goal.
634
+ let Goal { param_env, predicate } = goal. goal ( ) ;
635
635
let trait_ref = match predicate. kind ( ) . no_bound_vars ( ) {
636
636
Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( tr) ) ) => tr. trait_ref ,
637
637
Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( proj) ) )
@@ -645,7 +645,11 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
645
645
_ => return ,
646
646
} ;
647
647
648
- // Add ambiguity causes for reservation impls.
648
+ if trait_ref. references_error ( ) {
649
+ return ;
650
+ }
651
+
652
+ let mut candidates = goal. candidates ( ) ;
649
653
for cand in goal. candidates ( ) {
650
654
if let inspect:: ProbeKind :: TraitCandidate {
651
655
source : CandidateSource :: Impl ( def_id) ,
@@ -664,78 +668,68 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
664
668
}
665
669
}
666
670
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
+ } ;
687
676
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 ( ( ) ) ;
732
693
}
733
694
}
734
- }
695
+ Ok ( ty)
696
+ } ;
735
697
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
+ } ) ;
739
733
}
740
734
}
741
735
0 commit comments