1313use hir:: def_id:: { DefId , LOCAL_CRATE } ;
1414use syntax_pos:: DUMMY_SP ;
1515use traits:: { self , Normalized , SelectionContext , Obligation , ObligationCause , Reveal } ;
16+ use traits:: IntercrateMode ;
1617use traits:: select:: IntercrateAmbiguityCause ;
1718use ty:: { self , Ty , TyCtxt } ;
1819use ty:: subst:: Subst ;
1920
2021use infer:: { InferCtxt , InferOk } ;
2122
22- #[ derive( Copy , Clone ) ]
23- struct InferIsLocal ( bool ) ;
23+ #[ derive( Copy , Clone , Debug ) ]
24+ /// Whether we do the orphan check relative to this crate or
25+ /// to some remote crate.
26+ enum InCrate {
27+ Local ,
28+ Remote
29+ }
30+
31+ #[ derive( Debug , Copy , Clone ) ]
32+ pub enum Conflict {
33+ Upstream ,
34+ Downstream { used_to_be_broken : bool }
35+ }
2436
2537pub struct OverlapResult < ' tcx > {
2638 pub impl_header : ty:: ImplHeader < ' tcx > ,
@@ -31,16 +43,19 @@ pub struct OverlapResult<'tcx> {
3143/// `ImplHeader` with those types substituted
3244pub fn overlapping_impls < ' cx , ' gcx , ' tcx > ( infcx : & InferCtxt < ' cx , ' gcx , ' tcx > ,
3345 impl1_def_id : DefId ,
34- impl2_def_id : DefId )
46+ impl2_def_id : DefId ,
47+ intercrate_mode : IntercrateMode )
3548 -> Option < OverlapResult < ' tcx > >
3649{
3750 debug ! ( "impl_can_satisfy(\
3851 impl1_def_id={:?}, \
39- impl2_def_id={:?})",
52+ impl2_def_id={:?},
53+ intercrate_mode={:?})" ,
4054 impl1_def_id,
41- impl2_def_id) ;
55+ impl2_def_id,
56+ intercrate_mode) ;
4257
43- let selcx = & mut SelectionContext :: intercrate ( infcx) ;
58+ let selcx = & mut SelectionContext :: intercrate ( infcx, intercrate_mode ) ;
4459 overlap ( selcx, impl1_def_id, impl2_def_id)
4560}
4661
@@ -126,32 +141,49 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
126141}
127142
128143pub fn trait_ref_is_knowable < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
129- trait_ref : ty:: TraitRef < ' tcx > ) -> bool
144+ trait_ref : ty:: TraitRef < ' tcx > )
145+ -> Option < Conflict >
130146{
131147 debug ! ( "trait_ref_is_knowable(trait_ref={:?})" , trait_ref) ;
132-
133- // if the orphan rules pass, that means that no ancestor crate can
134- // impl this, so it's up to us.
135- if orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal ( false ) ) . is_ok ( ) {
136- debug ! ( "trait_ref_is_knowable: orphan check passed" ) ;
137- return true ;
148+ if orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Remote ) . is_ok ( ) {
149+ // A downstream or cousin crate is allowed to implement some
150+ // substitution of this trait-ref.
151+
152+ // A trait can be implementable for a trait ref by both the current
153+ // crate and crates downstream of it. Older versions of rustc
154+ // were not aware of this, causing incoherence (issue #43355).
155+ let used_to_be_broken =
156+ orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local ) . is_ok ( ) ;
157+ if used_to_be_broken {
158+ debug ! ( "trait_ref_is_knowable({:?}) - USED TO BE BROKEN" , trait_ref) ;
159+ }
160+ return Some ( Conflict :: Downstream { used_to_be_broken } ) ;
138161 }
139162
140- // if the trait is not marked fundamental, then it's always possible that
141- // an ancestor crate will impl this in the future, if they haven't
142- // already
143- if !trait_ref_is_local_or_fundamental ( tcx, trait_ref) {
144- debug ! ( "trait_ref_is_knowable: trait is neither local nor fundamental" ) ;
145- return false ;
163+ if trait_ref_is_local_or_fundamental ( tcx, trait_ref) {
164+ // This is a local or fundamental trait, so future-compatibility
165+ // is no concern. We know that downstream/cousin crates are not
166+ // allowed to implement a substitution of this trait ref, which
167+ // means impls could only come from dependencies of this crate,
168+ // which we already know about.
169+ return None ;
146170 }
147171
148- // find out when some downstream (or cousin) crate could impl this
149- // trait-ref, presuming that all the parameters were instantiated
150- // with downstream types. If not, then it could only be
151- // implemented by an upstream crate, which means that the impl
152- // must be visible to us, and -- since the trait is fundamental
153- // -- we can test.
154- orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal ( true ) ) . is_err ( )
172+ // This is a remote non-fundamental trait, so if another crate
173+ // can be the "final owner" of a substitution of this trait-ref,
174+ // they are allowed to implement it future-compatibly.
175+ //
176+ // However, if we are a final owner, then nobody else can be,
177+ // and if we are an intermediate owner, then we don't care
178+ // about future-compatibility, which means that we're OK if
179+ // we are an owner.
180+ if orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local ) . is_ok ( ) {
181+ debug ! ( "trait_ref_is_knowable: orphan check passed" ) ;
182+ return None ;
183+ } else {
184+ debug ! ( "trait_ref_is_knowable: nonlocal, nonfundamental, unowned" ) ;
185+ return Some ( Conflict :: Upstream ) ;
186+ }
155187}
156188
157189pub fn trait_ref_is_local_or_fundamental < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
@@ -189,30 +221,32 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
189221 return Ok ( ( ) ) ;
190222 }
191223
192- orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal ( false ) )
224+ orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local )
193225}
194226
195227fn orphan_check_trait_ref < ' tcx > ( tcx : TyCtxt ,
196228 trait_ref : ty:: TraitRef < ' tcx > ,
197- infer_is_local : InferIsLocal )
229+ in_crate : InCrate )
198230 -> Result < ( ) , OrphanCheckErr < ' tcx > >
199231{
200- debug ! ( "orphan_check_trait_ref(trait_ref={:?}, infer_is_local={ })" ,
201- trait_ref, infer_is_local . 0 ) ;
232+ debug ! ( "orphan_check_trait_ref(trait_ref={:?}, in_crate={:? })" ,
233+ trait_ref, in_crate ) ;
202234
203235 // First, create an ordered iterator over all the type parameters to the trait, with the self
204236 // type appearing first.
205237 // Find the first input type that either references a type parameter OR
206238 // some local type.
207239 for input_ty in trait_ref. input_types ( ) {
208- if ty_is_local ( tcx, input_ty, infer_is_local ) {
240+ if ty_is_local ( tcx, input_ty, in_crate ) {
209241 debug ! ( "orphan_check_trait_ref: ty_is_local `{:?}`" , input_ty) ;
210242
211243 // First local input type. Check that there are no
212244 // uncovered type parameters.
213- let uncovered_tys = uncovered_tys ( tcx, input_ty, infer_is_local ) ;
245+ let uncovered_tys = uncovered_tys ( tcx, input_ty, in_crate ) ;
214246 for uncovered_ty in uncovered_tys {
215- if let Some ( param) = uncovered_ty. walk ( ) . find ( |t| is_type_parameter ( t) ) {
247+ if let Some ( param) = uncovered_ty. walk ( )
248+ . find ( |t| is_possibly_remote_type ( t, in_crate) )
249+ {
216250 debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
217251 return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
218252 }
@@ -224,11 +258,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
224258
225259 // Otherwise, enforce invariant that there are no type
226260 // parameters reachable.
227- if !infer_is_local . 0 {
228- if let Some ( param ) = input_ty . walk ( ) . find ( |t| is_type_parameter ( t ) ) {
229- debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param ) ;
230- return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
231- }
261+ if let Some ( param ) = input_ty . walk ( )
262+ . find ( |t| is_possibly_remote_type ( t , in_crate ) )
263+ {
264+ debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
265+ return Err ( OrphanCheckErr :: UncoveredTy ( param ) ) ;
232266 }
233267 }
234268
@@ -237,29 +271,29 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
237271 return Err ( OrphanCheckErr :: NoLocalInputType ) ;
238272}
239273
240- fn uncovered_tys < ' tcx > ( tcx : TyCtxt , ty : Ty < ' tcx > , infer_is_local : InferIsLocal )
274+ fn uncovered_tys < ' tcx > ( tcx : TyCtxt , ty : Ty < ' tcx > , in_crate : InCrate )
241275 -> Vec < Ty < ' tcx > > {
242- if ty_is_local_constructor ( ty, infer_is_local ) {
276+ if ty_is_local_constructor ( ty, in_crate ) {
243277 vec ! [ ]
244278 } else if fundamental_ty ( tcx, ty) {
245279 ty. walk_shallow ( )
246- . flat_map ( |t| uncovered_tys ( tcx, t, infer_is_local ) )
280+ . flat_map ( |t| uncovered_tys ( tcx, t, in_crate ) )
247281 . collect ( )
248282 } else {
249283 vec ! [ ty]
250284 }
251285}
252286
253- fn is_type_parameter ( ty : Ty ) -> bool {
287+ fn is_possibly_remote_type ( ty : Ty , _in_crate : InCrate ) -> bool {
254288 match ty. sty {
255289 ty:: TyProjection ( ..) | ty:: TyParam ( ..) => true ,
256290 _ => false ,
257291 }
258292}
259293
260- fn ty_is_local ( tcx : TyCtxt , ty : Ty , infer_is_local : InferIsLocal ) -> bool {
261- ty_is_local_constructor ( ty, infer_is_local ) ||
262- fundamental_ty ( tcx, ty) && ty. walk_shallow ( ) . any ( |t| ty_is_local ( tcx, t, infer_is_local ) )
294+ fn ty_is_local ( tcx : TyCtxt , ty : Ty , in_crate : InCrate ) -> bool {
295+ ty_is_local_constructor ( ty, in_crate ) ||
296+ fundamental_ty ( tcx, ty) && ty. walk_shallow ( ) . any ( |t| ty_is_local ( tcx, t, in_crate ) )
263297}
264298
265299fn fundamental_ty ( tcx : TyCtxt , ty : Ty ) -> bool {
@@ -273,7 +307,16 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
273307 }
274308}
275309
276- fn ty_is_local_constructor ( ty : Ty , infer_is_local : InferIsLocal ) -> bool {
310+ fn def_id_is_local ( def_id : DefId , in_crate : InCrate ) -> bool {
311+ match in_crate {
312+ // The type is local to *this* crate - it will not be
313+ // local in any other crate.
314+ InCrate :: Remote => false ,
315+ InCrate :: Local => def_id. is_local ( )
316+ }
317+ }
318+
319+ fn ty_is_local_constructor ( ty : Ty , in_crate : InCrate ) -> bool {
277320 debug ! ( "ty_is_local_constructor({:?})" , ty) ;
278321
279322 match ty. sty {
@@ -296,20 +339,20 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal)-> bool {
296339 false
297340 }
298341
299- ty:: TyInfer ( ..) => {
300- infer_is_local. 0
301- }
302-
303- ty:: TyAdt ( def, _) => {
304- def. did . is_local ( )
305- }
342+ ty:: TyInfer ( ..) => match in_crate {
343+ InCrate :: Local => false ,
344+ // The inference variable might be unified with a local
345+ // type in that remote crate.
346+ InCrate :: Remote => true ,
347+ } ,
306348
307- ty:: TyForeign ( did) => {
308- did. is_local ( )
309- }
349+ ty:: TyAdt ( def, _) => def_id_is_local ( def. did , in_crate) ,
350+ ty:: TyForeign ( did) => def_id_is_local ( did, in_crate) ,
310351
311352 ty:: TyDynamic ( ref tt, ..) => {
312- tt. principal ( ) . map_or ( false , |p| p. def_id ( ) . is_local ( ) )
353+ tt. principal ( ) . map_or ( false , |p| {
354+ def_id_is_local ( p. def_id ( ) , in_crate)
355+ } )
313356 }
314357
315358 ty:: TyError => {
0 commit comments