@@ -92,10 +92,10 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
92
92
93
93
inferred_obligations : SnapshotVec < InferredObligationsSnapshotVecDelegate < ' tcx > > ,
94
94
95
- intercrate_ambiguity_causes : Vec < IntercrateAmbiguityCause > ,
95
+ intercrate_ambiguity_causes : Option < Vec < IntercrateAmbiguityCause > > ,
96
96
}
97
97
98
- #[ derive( Clone ) ]
98
+ #[ derive( Clone , Debug ) ]
99
99
pub enum IntercrateAmbiguityCause {
100
100
DownstreamCrate {
101
101
trait_desc : String ,
@@ -423,7 +423,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
423
423
freshener : infcx. freshener ( ) ,
424
424
intercrate : None ,
425
425
inferred_obligations : SnapshotVec :: new ( ) ,
426
- intercrate_ambiguity_causes : Vec :: new ( ) ,
426
+ intercrate_ambiguity_causes : None ,
427
427
}
428
428
}
429
429
@@ -435,10 +435,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
435
435
freshener : infcx. freshener ( ) ,
436
436
intercrate : Some ( mode) ,
437
437
inferred_obligations : SnapshotVec :: new ( ) ,
438
- intercrate_ambiguity_causes : Vec :: new ( ) ,
438
+ intercrate_ambiguity_causes : None ,
439
439
}
440
440
}
441
441
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
+
442
462
pub fn infcx ( & self ) -> & ' cx InferCtxt < ' cx , ' gcx , ' tcx > {
443
463
self . infcx
444
464
}
@@ -451,10 +471,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
451
471
self . infcx
452
472
}
453
473
454
- pub fn intercrate_ambiguity_causes ( & self ) -> & [ IntercrateAmbiguityCause ] {
455
- & self . intercrate_ambiguity_causes
456
- }
457
-
458
474
/// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
459
475
/// context's self.
460
476
fn in_snapshot < R , F > ( & mut self , f : F ) -> R
@@ -828,19 +844,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
828
844
debug ! ( "evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous" ,
829
845
stack. fresh_trait_ref) ;
830
846
// 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
+ }
844
864
}
845
865
}
846
866
return EvaluatedToAmbig ;
@@ -1092,25 +1112,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1092
1112
None => { }
1093
1113
Some ( conflict) => {
1094
1114
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
+ }
1114
1138
}
1115
1139
return Ok ( None ) ;
1116
1140
}
0 commit comments