13
13
use self :: SelectionCandidate :: * ;
14
14
use self :: EvaluationResult :: * ;
15
15
16
- use super :: coherence;
16
+ use super :: coherence:: { self , Conflict } ;
17
17
use super :: DerivedObligationCause ;
18
+ use super :: IntercrateMode ;
18
19
use super :: project;
19
20
use super :: project:: { normalize_with_depth, Normalized , ProjectionCacheKey } ;
20
21
use super :: { PredicateObligation , TraitObligation , ObligationCause } ;
@@ -87,7 +88,7 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
87
88
/// other words, we consider `$0 : Bar` to be unimplemented if
88
89
/// there is no type that the user could *actually name* that
89
90
/// would satisfy it. This avoids crippling inference, basically.
90
- intercrate : bool ,
91
+ intercrate : Option < IntercrateMode > ,
91
92
92
93
inferred_obligations : SnapshotVec < InferredObligationsSnapshotVecDelegate < ' tcx > > ,
93
94
@@ -111,21 +112,24 @@ impl IntercrateAmbiguityCause {
111
112
/// See #23980 for details.
112
113
pub fn add_intercrate_ambiguity_hint < ' a , ' tcx > ( & self ,
113
114
err : & mut :: errors:: DiagnosticBuilder ) {
115
+ err. note ( & self . intercrate_ambiguity_hint ( ) ) ;
116
+ }
117
+
118
+ pub fn intercrate_ambiguity_hint ( & self ) -> String {
114
119
match self {
115
120
& IntercrateAmbiguityCause :: DownstreamCrate { ref trait_desc, ref self_desc } => {
116
121
let self_desc = if let & Some ( ref ty) = self_desc {
117
122
format ! ( " for type `{}`" , ty)
118
123
} else { "" . to_string ( ) } ;
119
- err. note ( & format ! ( "downstream crates may implement trait `{}`{}" ,
120
- trait_desc, self_desc) ) ;
124
+ format ! ( "downstream crates may implement trait `{}`{}" , trait_desc, self_desc)
121
125
}
122
126
& IntercrateAmbiguityCause :: UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
123
127
let self_desc = if let & Some ( ref ty) = self_desc {
124
128
format ! ( " for type `{}`" , ty)
125
129
} else { "" . to_string ( ) } ;
126
- err . note ( & format ! ( "upstream crates may add new impl of trait `{}`{} \
127
- in future versions",
128
- trait_desc, self_desc) ) ;
130
+ format ! ( "upstream crates may add new impl of trait `{}`{} \
131
+ in future versions",
132
+ trait_desc, self_desc)
129
133
}
130
134
}
131
135
}
@@ -417,17 +421,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
417
421
SelectionContext {
418
422
infcx,
419
423
freshener : infcx. freshener ( ) ,
420
- intercrate : false ,
424
+ intercrate : None ,
421
425
inferred_obligations : SnapshotVec :: new ( ) ,
422
426
intercrate_ambiguity_causes : Vec :: new ( ) ,
423
427
}
424
428
}
425
429
426
- pub fn intercrate ( infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ) -> SelectionContext < ' cx , ' gcx , ' tcx > {
430
+ pub fn intercrate ( infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
431
+ mode : IntercrateMode ) -> SelectionContext < ' cx , ' gcx , ' tcx > {
432
+ debug ! ( "intercrate({:?})" , mode) ;
427
433
SelectionContext {
428
434
infcx,
429
435
freshener : infcx. freshener ( ) ,
430
- intercrate : true ,
436
+ intercrate : Some ( mode ) ,
431
437
inferred_obligations : SnapshotVec :: new ( ) ,
432
438
intercrate_ambiguity_causes : Vec :: new ( ) ,
433
439
}
@@ -758,7 +764,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
758
764
debug ! ( "evaluate_trait_predicate_recursively({:?})" ,
759
765
obligation) ;
760
766
761
- if !self . intercrate && obligation. is_global ( ) {
767
+ if !self . intercrate . is_some ( ) && obligation. is_global ( ) {
762
768
// If a param env is consistent, global obligations do not depend on its particular
763
769
// value in order to work, so we can clear out the param env and get better
764
770
// caching. (If the current param env is inconsistent, we don't care what happens).
@@ -814,7 +820,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
814
820
// terms of `Fn` etc, but we could probably make this more
815
821
// precise still.
816
822
let unbound_input_types = stack. fresh_trait_ref . input_types ( ) . any ( |ty| ty. is_fresh ( ) ) ;
817
- if unbound_input_types && self . intercrate {
823
+ // this check was an imperfect workaround for a bug n the old
824
+ // intercrate mode, it should be removed when that goes away.
825
+ if unbound_input_types &&
826
+ self . intercrate == Some ( IntercrateMode :: Issue43355 )
827
+ {
818
828
debug ! ( "evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous" ,
819
829
stack. fresh_trait_ref) ;
820
830
// Heuristics: show the diagnostics when there are no candidates in crate.
@@ -1077,28 +1087,32 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1077
1087
return Ok ( None ) ;
1078
1088
}
1079
1089
1080
- if !self . is_knowable ( stack) {
1081
- debug ! ( "coherence stage: not knowable" ) ;
1082
- // Heuristics: show the diagnostics when there are no candidates in crate.
1083
- let candidate_set = self . assemble_candidates ( stack) ?;
1084
- if !candidate_set. ambiguous && candidate_set. vec . is_empty ( ) {
1085
- let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
1086
- let self_ty = trait_ref. self_ty ( ) ;
1087
- let trait_desc = trait_ref. to_string ( ) ;
1088
- let self_desc = if self_ty. has_concrete_skeleton ( ) {
1089
- Some ( self_ty. to_string ( ) )
1090
- } else {
1091
- None
1092
- } ;
1093
- let cause = if !coherence:: trait_ref_is_local_or_fundamental ( self . tcx ( ) ,
1094
- trait_ref) {
1095
- IntercrateAmbiguityCause :: UpstreamCrateUpdate { trait_desc, self_desc }
1096
- } else {
1097
- IntercrateAmbiguityCause :: DownstreamCrate { trait_desc, self_desc }
1098
- } ;
1099
- self . intercrate_ambiguity_causes . push ( cause) ;
1090
+ match self . is_knowable ( stack) {
1091
+ None => { }
1092
+ Some ( conflict) => {
1093
+ debug ! ( "coherence stage: not knowable" ) ;
1094
+ // Heuristics: show the diagnostics when there are no candidates in crate.
1095
+ let candidate_set = self . assemble_candidates ( stack) ?;
1096
+ if !candidate_set. ambiguous && candidate_set. vec . iter ( ) . all ( |c| {
1097
+ !self . evaluate_candidate ( stack, & c) . may_apply ( )
1098
+ } ) {
1099
+ let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
1100
+ let self_ty = trait_ref. self_ty ( ) ;
1101
+ let trait_desc = trait_ref. to_string ( ) ;
1102
+ let self_desc = if self_ty. has_concrete_skeleton ( ) {
1103
+ Some ( self_ty. to_string ( ) )
1104
+ } else {
1105
+ None
1106
+ } ;
1107
+ let cause = if let Conflict :: Upstream = conflict {
1108
+ IntercrateAmbiguityCause :: UpstreamCrateUpdate { trait_desc, self_desc }
1109
+ } else {
1110
+ IntercrateAmbiguityCause :: DownstreamCrate { trait_desc, self_desc }
1111
+ } ;
1112
+ self . intercrate_ambiguity_causes . push ( cause) ;
1113
+ }
1114
+ return Ok ( None ) ;
1100
1115
}
1101
- return Ok ( None ) ;
1102
1116
}
1103
1117
1104
1118
let candidate_set = self . assemble_candidates ( stack) ?;
@@ -1205,12 +1219,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1205
1219
1206
1220
fn is_knowable < ' o > ( & mut self ,
1207
1221
stack : & TraitObligationStack < ' o , ' tcx > )
1208
- -> bool
1222
+ -> Option < Conflict >
1209
1223
{
1210
- debug ! ( "is_knowable(intercrate={})" , self . intercrate) ;
1224
+ debug ! ( "is_knowable(intercrate={:? })" , self . intercrate) ;
1211
1225
1212
- if !self . intercrate {
1213
- return true ;
1226
+ if !self . intercrate . is_some ( ) {
1227
+ return None ;
1214
1228
}
1215
1229
1216
1230
let obligation = & stack. obligation ;
@@ -1221,7 +1235,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1221
1235
// bound regions
1222
1236
let trait_ref = predicate. skip_binder ( ) . trait_ref ;
1223
1237
1224
- coherence:: trait_ref_is_knowable ( self . tcx ( ) , trait_ref)
1238
+ let result = coherence:: trait_ref_is_knowable ( self . tcx ( ) , trait_ref) ;
1239
+ if let ( Some ( Conflict :: Downstream { used_to_be_broken : true } ) ,
1240
+ Some ( IntercrateMode :: Issue43355 ) ) = ( result, self . intercrate ) {
1241
+ debug ! ( "is_knowable: IGNORING conflict to be bug-compatible with #43355" ) ;
1242
+ None
1243
+ } else {
1244
+ result
1245
+ }
1225
1246
}
1226
1247
1227
1248
/// Returns true if the global caches can be used.
@@ -1246,7 +1267,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1246
1267
// the master cache. Since coherence executes pretty quickly,
1247
1268
// it's not worth going to more trouble to increase the
1248
1269
// hit-rate I don't think.
1249
- if self . intercrate {
1270
+ if self . intercrate . is_some ( ) {
1250
1271
return false ;
1251
1272
}
1252
1273
0 commit comments