@@ -92,10 +92,10 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
9292
9393 inferred_obligations : SnapshotVec < InferredObligationsSnapshotVecDelegate < ' tcx > > ,
9494
95- intercrate_ambiguity_causes : Vec < IntercrateAmbiguityCause > ,
95+ intercrate_ambiguity_causes : Option < Vec < IntercrateAmbiguityCause > > ,
9696}
9797
98- #[ derive( Clone ) ]
98+ #[ derive( Clone , Debug ) ]
9999pub enum IntercrateAmbiguityCause {
100100 DownstreamCrate {
101101 trait_desc : String ,
@@ -423,7 +423,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
423423 freshener : infcx. freshener ( ) ,
424424 intercrate : None ,
425425 inferred_obligations : SnapshotVec :: new ( ) ,
426- intercrate_ambiguity_causes : Vec :: new ( ) ,
426+ intercrate_ambiguity_causes : None ,
427427 }
428428 }
429429
@@ -435,10 +435,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
435435 freshener : infcx. freshener ( ) ,
436436 intercrate : Some ( mode) ,
437437 inferred_obligations : SnapshotVec :: new ( ) ,
438- intercrate_ambiguity_causes : Vec :: new ( ) ,
438+ intercrate_ambiguity_causes : None ,
439439 }
440440 }
441441
442+ /// Enables tracking of intercrate ambiguity causes. These are
443+ /// used in coherence to give improved diagnostics. We don't do
444+ /// this until we detect a coherence error because it can lead to
445+ /// false overflow results (#47139) and because it costs
446+ /// computation time.
447+ pub fn enable_tracking_intercrate_ambiguity_causes ( & mut self ) {
448+ assert ! ( self . intercrate. is_some( ) ) ;
449+ assert ! ( self . intercrate_ambiguity_causes. is_none( ) ) ;
450+ self . intercrate_ambiguity_causes = Some ( vec ! [ ] ) ;
451+ debug ! ( "selcx: enable_tracking_intercrate_ambiguity_causes" ) ;
452+ }
453+
454+ /// Gets the intercrate ambiguity causes collected since tracking
455+ /// was enabled and disables tracking at the same time. If
456+ /// tracking is not enabled, just returns an empty vector.
457+ pub fn take_intercrate_ambiguity_causes ( & mut self ) -> Vec < IntercrateAmbiguityCause > {
458+ assert ! ( self . intercrate. is_some( ) ) ;
459+ self . intercrate_ambiguity_causes . take ( ) . unwrap_or ( vec ! [ ] )
460+ }
461+
442462 pub fn infcx ( & self ) -> & ' cx InferCtxt < ' cx , ' gcx , ' tcx > {
443463 self . infcx
444464 }
@@ -451,10 +471,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
451471 self . infcx
452472 }
453473
454- pub fn intercrate_ambiguity_causes ( & self ) -> & [ IntercrateAmbiguityCause ] {
455- & self . intercrate_ambiguity_causes
456- }
457-
458474 /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
459475 /// context's self.
460476 fn in_snapshot < R , F > ( & mut self , f : F ) -> R
@@ -828,19 +844,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
828844 debug ! ( "evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous" ,
829845 stack. fresh_trait_ref) ;
830846 // Heuristics: show the diagnostics when there are no candidates in crate.
831- if let Ok ( candidate_set) = self . assemble_candidates ( stack) {
832- if !candidate_set. ambiguous && candidate_set. vec . is_empty ( ) {
833- let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
834- let self_ty = trait_ref. self_ty ( ) ;
835- let cause = IntercrateAmbiguityCause :: DownstreamCrate {
836- trait_desc : trait_ref. to_string ( ) ,
837- self_desc : if self_ty. has_concrete_skeleton ( ) {
838- Some ( self_ty. to_string ( ) )
839- } else {
840- None
841- } ,
842- } ;
843- self . intercrate_ambiguity_causes . push ( cause) ;
847+ if self . intercrate_ambiguity_causes . is_some ( ) {
848+ debug ! ( "evaluate_stack: intercrate_ambiguity_causes is some" ) ;
849+ if let Ok ( candidate_set) = self . assemble_candidates ( stack) {
850+ if !candidate_set. ambiguous && candidate_set. vec . is_empty ( ) {
851+ let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
852+ let self_ty = trait_ref. self_ty ( ) ;
853+ let cause = IntercrateAmbiguityCause :: DownstreamCrate {
854+ trait_desc : trait_ref. to_string ( ) ,
855+ self_desc : if self_ty. has_concrete_skeleton ( ) {
856+ Some ( self_ty. to_string ( ) )
857+ } else {
858+ None
859+ } ,
860+ } ;
861+ debug ! ( "evaluate_stack: pushing cause = {:?}" , cause) ;
862+ self . intercrate_ambiguity_causes . as_mut ( ) . unwrap ( ) . push ( cause) ;
863+ }
844864 }
845865 }
846866 return EvaluatedToAmbig ;
@@ -1092,25 +1112,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10921112 None => { }
10931113 Some ( conflict) => {
10941114 debug ! ( "coherence stage: not knowable" ) ;
1095- // Heuristics: show the diagnostics when there are no candidates in crate.
1096- let candidate_set = self . assemble_candidates ( stack) ?;
1097- if !candidate_set. ambiguous && candidate_set. vec . iter ( ) . all ( |c| {
1098- !self . evaluate_candidate ( stack, & c) . may_apply ( )
1099- } ) {
1100- let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
1101- let self_ty = trait_ref. self_ty ( ) ;
1102- let trait_desc = trait_ref. to_string ( ) ;
1103- let self_desc = if self_ty. has_concrete_skeleton ( ) {
1104- Some ( self_ty. to_string ( ) )
1105- } else {
1106- None
1107- } ;
1108- let cause = if let Conflict :: Upstream = conflict {
1109- IntercrateAmbiguityCause :: UpstreamCrateUpdate { trait_desc, self_desc }
1110- } else {
1111- IntercrateAmbiguityCause :: DownstreamCrate { trait_desc, self_desc }
1112- } ;
1113- self . intercrate_ambiguity_causes . push ( cause) ;
1115+ if self . intercrate_ambiguity_causes . is_some ( ) {
1116+ debug ! ( "evaluate_stack: intercrate_ambiguity_causes is some" ) ;
1117+ // Heuristics: show the diagnostics when there are no candidates in crate.
1118+ let candidate_set = self . assemble_candidates ( stack) ?;
1119+ if !candidate_set. ambiguous && candidate_set. vec . iter ( ) . all ( |c| {
1120+ !self . evaluate_candidate ( stack, & c) . may_apply ( )
1121+ } ) {
1122+ let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
1123+ let self_ty = trait_ref. self_ty ( ) ;
1124+ let trait_desc = trait_ref. to_string ( ) ;
1125+ let self_desc = if self_ty. has_concrete_skeleton ( ) {
1126+ Some ( self_ty. to_string ( ) )
1127+ } else {
1128+ None
1129+ } ;
1130+ let cause = if let Conflict :: Upstream = conflict {
1131+ IntercrateAmbiguityCause :: UpstreamCrateUpdate { trait_desc, self_desc }
1132+ } else {
1133+ IntercrateAmbiguityCause :: DownstreamCrate { trait_desc, self_desc }
1134+ } ;
1135+ debug ! ( "evaluate_stack: pushing cause = {:?}" , cause) ;
1136+ self . intercrate_ambiguity_causes . as_mut ( ) . unwrap ( ) . push ( cause) ;
1137+ }
11141138 }
11151139 return Ok ( None ) ;
11161140 }
0 commit comments