@@ -20,16 +20,17 @@ use ty::subst::Subst;
2020use infer:: { InferCtxt , InferOk } ;
2121
2222#[ derive( Copy , Clone , Debug ) ]
23- enum InferIsLocal {
24- BrokenYes ,
25- Yes ,
26- No
23+ /// Whether we do the orphan check relative to this crate or
24+ /// to some remote crate.
25+ enum InCrate {
26+ Local ,
27+ Remote
2728}
2829
2930#[ derive( Debug , Copy , Clone ) ]
3031pub enum Conflict {
3132 Upstream ,
32- Downstream
33+ Downstream { used_to_be_broken : bool }
3334}
3435
3536pub struct OverlapResult < ' tcx > {
@@ -136,21 +137,23 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
136137}
137138
138139pub fn trait_ref_is_knowable < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
139- trait_ref : ty:: TraitRef < ' tcx > ,
140- broken : bool )
140+ trait_ref : ty:: TraitRef < ' tcx > )
141141 -> Option < Conflict >
142142{
143- debug ! ( "trait_ref_is_knowable(trait_ref={:?}, broken={:?})" , trait_ref, broken) ;
144- let mode = if broken {
145- InferIsLocal :: BrokenYes
146- } else {
147- InferIsLocal :: Yes
148- } ;
149- if orphan_check_trait_ref ( tcx, trait_ref, mode) . is_ok ( ) {
143+ debug ! ( "trait_ref_is_knowable(trait_ref={:?})" , trait_ref) ;
144+ if orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Remote ) . is_ok ( ) {
150145 // A downstream or cousin crate is allowed to implement some
151146 // substitution of this trait-ref.
152- debug ! ( "trait_ref_is_knowable: downstream crate might implement" ) ;
153- return Some ( Conflict :: Downstream ) ;
147+
148+ // A trait can be implementable for a trait ref by both the current
149+ // crate and crates downstream of it. Older versions of rustc
150+ // were not aware of this, causing incoherence (issue #43355).
151+ let used_to_be_broken =
152+ orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local ) . is_ok ( ) ;
153+ if used_to_be_broken {
154+ debug ! ( "trait_ref_is_knowable({:?}) - USED TO BE BROKEN" , trait_ref) ;
155+ }
156+ return Some ( Conflict :: Downstream { used_to_be_broken } ) ;
154157 }
155158
156159 if trait_ref_is_local_or_fundamental ( tcx, trait_ref) {
@@ -161,6 +164,7 @@ pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
161164 // which we already know about.
162165 return None ;
163166 }
167+
164168 // This is a remote non-fundamental trait, so if another crate
165169 // can be the "final owner" of a substitution of this trait-ref,
166170 // they are allowed to implement it future-compatibly.
@@ -169,7 +173,7 @@ pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
169173 // and if we are an intermediate owner, then we don't care
170174 // about future-compatibility, which means that we're OK if
171175 // we are an owner.
172- if orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal :: No ) . is_ok ( ) {
176+ if orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local ) . is_ok ( ) {
173177 debug ! ( "trait_ref_is_knowable: orphan check passed" ) ;
174178 return None ;
175179 } else {
@@ -213,31 +217,31 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
213217 return Ok ( ( ) ) ;
214218 }
215219
216- orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal :: No )
220+ orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local )
217221}
218222
219223fn orphan_check_trait_ref < ' tcx > ( tcx : TyCtxt ,
220224 trait_ref : ty:: TraitRef < ' tcx > ,
221- infer_is_local : InferIsLocal )
225+ in_crate : InCrate )
222226 -> Result < ( ) , OrphanCheckErr < ' tcx > >
223227{
224- debug ! ( "orphan_check_trait_ref(trait_ref={:?}, infer_is_local ={:?})" ,
225- trait_ref, infer_is_local ) ;
228+ debug ! ( "orphan_check_trait_ref(trait_ref={:?}, in_crate ={:?})" ,
229+ trait_ref, in_crate ) ;
226230
227231 // First, create an ordered iterator over all the type parameters to the trait, with the self
228232 // type appearing first.
229233 // Find the first input type that either references a type parameter OR
230234 // some local type.
231235 for input_ty in trait_ref. input_types ( ) {
232- if ty_is_local ( tcx, input_ty, infer_is_local ) {
236+ if ty_is_local ( tcx, input_ty, in_crate ) {
233237 debug ! ( "orphan_check_trait_ref: ty_is_local `{:?}`" , input_ty) ;
234238
235239 // First local input type. Check that there are no
236240 // uncovered type parameters.
237- let uncovered_tys = uncovered_tys ( tcx, input_ty, infer_is_local ) ;
241+ let uncovered_tys = uncovered_tys ( tcx, input_ty, in_crate ) ;
238242 for uncovered_ty in uncovered_tys {
239243 if let Some ( param) = uncovered_ty. walk ( )
240- . find ( |t| is_possibly_remote_type ( t, infer_is_local ) )
244+ . find ( |t| is_possibly_remote_type ( t, in_crate ) )
241245 {
242246 debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
243247 return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
@@ -251,7 +255,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
251255 // Otherwise, enforce invariant that there are no type
252256 // parameters reachable.
253257 if let Some ( param) = input_ty. walk ( )
254- . find ( |t| is_possibly_remote_type ( t, infer_is_local ) )
258+ . find ( |t| is_possibly_remote_type ( t, in_crate ) )
255259 {
256260 debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
257261 return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
@@ -263,29 +267,29 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
263267 return Err ( OrphanCheckErr :: NoLocalInputType ) ;
264268}
265269
266- fn uncovered_tys < ' tcx > ( tcx : TyCtxt , ty : Ty < ' tcx > , infer_is_local : InferIsLocal )
270+ fn uncovered_tys < ' tcx > ( tcx : TyCtxt , ty : Ty < ' tcx > , in_crate : InCrate )
267271 -> Vec < Ty < ' tcx > > {
268- if ty_is_local_constructor ( ty, infer_is_local ) {
272+ if ty_is_local_constructor ( ty, in_crate ) {
269273 vec ! [ ]
270274 } else if fundamental_ty ( tcx, ty) {
271275 ty. walk_shallow ( )
272- . flat_map ( |t| uncovered_tys ( tcx, t, infer_is_local ) )
276+ . flat_map ( |t| uncovered_tys ( tcx, t, in_crate ) )
273277 . collect ( )
274278 } else {
275279 vec ! [ ty]
276280 }
277281}
278282
279- fn is_possibly_remote_type ( ty : Ty , _infer_is_local : InferIsLocal ) -> bool {
283+ fn is_possibly_remote_type ( ty : Ty , _in_crate : InCrate ) -> bool {
280284 match ty. sty {
281285 ty:: TyProjection ( ..) | ty:: TyParam ( ..) => true ,
282286 _ => false ,
283287 }
284288}
285289
286- fn ty_is_local ( tcx : TyCtxt , ty : Ty , infer_is_local : InferIsLocal ) -> bool {
287- ty_is_local_constructor ( ty, infer_is_local ) ||
288- fundamental_ty ( tcx, ty) && ty. walk_shallow ( ) . any ( |t| ty_is_local ( tcx, t, infer_is_local ) )
290+ fn ty_is_local ( tcx : TyCtxt , ty : Ty , in_crate : InCrate ) -> bool {
291+ ty_is_local_constructor ( ty, in_crate ) ||
292+ fundamental_ty ( tcx, ty) && ty. walk_shallow ( ) . any ( |t| ty_is_local ( tcx, t, in_crate ) )
289293}
290294
291295fn fundamental_ty ( tcx : TyCtxt , ty : Ty ) -> bool {
@@ -299,15 +303,16 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
299303 }
300304}
301305
302- fn def_id_is_local ( def_id : DefId , infer_is_local : InferIsLocal ) -> bool {
303- match infer_is_local {
304- InferIsLocal :: Yes => false ,
305- InferIsLocal :: No |
306- InferIsLocal :: BrokenYes => def_id. is_local ( )
306+ fn def_id_is_local ( def_id : DefId , in_crate : InCrate ) -> bool {
307+ match in_crate {
308+ // The type is local to *this* crate - it will not be
309+ // local in any other crate.
310+ InCrate :: Remote => false ,
311+ InCrate :: Local => def_id. is_local ( )
307312 }
308313}
309314
310- fn ty_is_local_constructor ( ty : Ty , infer_is_local : InferIsLocal ) -> bool {
315+ fn ty_is_local_constructor ( ty : Ty , in_crate : InCrate ) -> bool {
311316 debug ! ( "ty_is_local_constructor({:?})" , ty) ;
312317
313318 match ty. sty {
@@ -330,18 +335,19 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal) -> bool {
330335 false
331336 }
332337
333- ty:: TyInfer ( ..) => match infer_is_local {
334- InferIsLocal :: No => false ,
335- InferIsLocal :: Yes |
336- InferIsLocal :: BrokenYes => true
338+ ty:: TyInfer ( ..) => match in_crate {
339+ InCrate :: Local => false ,
340+ // The inference variable might be unified with a local
341+ // type in that remote crate.
342+ InCrate :: Remote => true ,
337343 } ,
338344
339- ty:: TyAdt ( def, _) => def_id_is_local ( def. did , infer_is_local ) ,
340- ty:: TyForeign ( did) => def_id_is_local ( did, infer_is_local ) ,
345+ ty:: TyAdt ( def, _) => def_id_is_local ( def. did , in_crate ) ,
346+ ty:: TyForeign ( did) => def_id_is_local ( did, in_crate ) ,
341347
342348 ty:: TyDynamic ( ref tt, ..) => {
343349 tt. principal ( ) . map_or ( false , |p| {
344- def_id_is_local ( p. def_id ( ) , infer_is_local )
350+ def_id_is_local ( p. def_id ( ) , in_crate )
345351 } )
346352 }
347353
0 commit comments