@@ -15,6 +15,7 @@ use self::EvaluationResult::*;
15
15
16
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 && false {
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.
@@ -1212,9 +1222,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1212
1222
stack : & TraitObligationStack < ' o , ' tcx > )
1213
1223
-> Option < Conflict >
1214
1224
{
1215
- debug ! ( "is_knowable(intercrate={})" , self . intercrate) ;
1225
+ debug ! ( "is_knowable(intercrate={:? })" , self . intercrate) ;
1216
1226
1217
- if !self . intercrate {
1227
+ if !self . intercrate . is_some ( ) {
1218
1228
return None ;
1219
1229
}
1220
1230
@@ -1226,7 +1236,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1226
1236
// bound regions
1227
1237
let trait_ref = predicate. skip_binder ( ) . trait_ref ;
1228
1238
1229
- coherence:: trait_ref_is_knowable ( self . tcx ( ) , trait_ref)
1239
+ let result = coherence:: trait_ref_is_knowable ( self . tcx ( ) , trait_ref) ;
1240
+ if let ( Some ( Conflict :: Downstream { used_to_be_broken : true } ) ,
1241
+ Some ( IntercrateMode :: Issue43355 ) ) = ( result, self . intercrate ) {
1242
+ debug ! ( "is_knowable: IGNORING conflict to be bug-compatible with #43355" ) ;
1243
+ None
1244
+ } else {
1245
+ result
1246
+ }
1230
1247
}
1231
1248
1232
1249
/// Returns true if the global caches can be used.
@@ -1251,7 +1268,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1251
1268
// the master cache. Since coherence executes pretty quickly,
1252
1269
// it's not worth going to more trouble to increase the
1253
1270
// hit-rate I don't think.
1254
- if self . intercrate {
1271
+ if self . intercrate . is_some ( ) {
1255
1272
return false ;
1256
1273
}
1257
1274
0 commit comments