@@ -19,18 +19,8 @@ use ty::subst::Subst;
1919
2020use infer:: { InferCtxt , InferOk } ;
2121
22- #[ derive( Copy , Clone , Debug ) ]
23- enum InferIsLocal {
24- BrokenYes ,
25- Yes ,
26- No
27- }
28-
29- #[ derive( Debug , Copy , Clone ) ]
30- pub enum Conflict {
31- Upstream ,
32- Downstream
33- }
22+ #[ derive( Copy , Clone ) ]
23+ struct InferIsLocal ( bool ) ;
3424
3525pub struct OverlapResult < ' tcx > {
3626 pub impl_header : ty:: ImplHeader < ' tcx > ,
@@ -136,46 +126,32 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
136126}
137127
138128pub fn trait_ref_is_knowable < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
139- trait_ref : ty:: TraitRef < ' tcx > ,
140- broken : bool )
141- -> Option < Conflict >
129+ trait_ref : ty:: TraitRef < ' tcx > ) -> bool
142130{
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 ( ) {
150- // A downstream or cousin crate is allowed to implement some
151- // substitution of this trait-ref.
152- debug ! ( "trait_ref_is_knowable: downstream crate might implement" ) ;
153- return Some ( Conflict :: Downstream ) ;
154- }
131+ debug ! ( "trait_ref_is_knowable(trait_ref={:?})" , trait_ref) ;
155132
156- if trait_ref_is_local_or_fundamental ( tcx, trait_ref) {
157- // This is a local or fundamental trait, so future-compatibility
158- // is no concern. We know that downstream/cousin crates are not
159- // allowed to implement a substitution of this trait ref, which
160- // means impls could only come from dependencies of this crate,
161- // which we already know about.
162- return None ;
163- }
164- // This is a remote non-fundamental trait, so if another crate
165- // can be the "final owner" of a substitution of this trait-ref,
166- // they are allowed to implement it future-compatibly.
167- //
168- // However, if we are a final owner, then nobody else can be,
169- // and if we are an intermediate owner, then we don't care
170- // about future-compatibility, which means that we're OK if
171- // we are an owner.
172- if orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal :: No ) . is_ok ( ) {
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 ( ) {
173136 debug ! ( "trait_ref_is_knowable: orphan check passed" ) ;
174- return None ;
175- } else {
176- debug ! ( "trait_ref_is_knowable: nonlocal, nonfundamental, unowned" ) ;
177- return Some ( Conflict :: Upstream ) ;
137+ return true ;
138+ }
139+
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 ;
178146 }
147+
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 ( )
179155}
180156
181157pub fn trait_ref_is_local_or_fundamental < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
@@ -213,16 +189,16 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
213189 return Ok ( ( ) ) ;
214190 }
215191
216- orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal :: No )
192+ orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal ( false ) )
217193}
218194
219195fn orphan_check_trait_ref < ' tcx > ( tcx : TyCtxt ,
220196 trait_ref : ty:: TraitRef < ' tcx > ,
221197 infer_is_local : InferIsLocal )
222198 -> Result < ( ) , OrphanCheckErr < ' tcx > >
223199{
224- debug ! ( "orphan_check_trait_ref(trait_ref={:?}, infer_is_local={:? })" ,
225- trait_ref, infer_is_local) ;
200+ debug ! ( "orphan_check_trait_ref(trait_ref={:?}, infer_is_local={})" ,
201+ trait_ref, infer_is_local. 0 ) ;
226202
227203 // First, create an ordered iterator over all the type parameters to the trait, with the self
228204 // type appearing first.
@@ -236,9 +212,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
236212 // uncovered type parameters.
237213 let uncovered_tys = uncovered_tys ( tcx, input_ty, infer_is_local) ;
238214 for uncovered_ty in uncovered_tys {
239- if let Some ( param) = uncovered_ty. walk ( )
240- . find ( |t| is_possibly_remote_type ( t, infer_is_local) )
241- {
215+ if let Some ( param) = uncovered_ty. walk ( ) . find ( |t| is_type_parameter ( t) ) {
242216 debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
243217 return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
244218 }
@@ -250,11 +224,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
250224
251225 // Otherwise, enforce invariant that there are no type
252226 // parameters reachable.
253- if let Some ( param ) = input_ty . walk ( )
254- . find ( |t| is_possibly_remote_type ( t , infer_is_local ) )
255- {
256- debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
257- return Err ( OrphanCheckErr :: UncoveredTy ( param ) ) ;
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+ }
258232 }
259233 }
260234
@@ -276,7 +250,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
276250 }
277251}
278252
279- fn is_possibly_remote_type ( ty : Ty , _infer_is_local : InferIsLocal ) -> bool {
253+ fn is_type_parameter ( ty : Ty ) -> bool {
280254 match ty. sty {
281255 ty:: TyProjection ( ..) | ty:: TyParam ( ..) => true ,
282256 _ => false ,
@@ -299,15 +273,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
299273 }
300274}
301275
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 ( )
307- }
308- }
309-
310- fn ty_is_local_constructor ( ty : Ty , infer_is_local : InferIsLocal ) -> bool {
276+ fn ty_is_local_constructor ( ty : Ty , infer_is_local : InferIsLocal ) -> bool {
311277 debug ! ( "ty_is_local_constructor({:?})" , ty) ;
312278
313279 match ty. sty {
@@ -330,19 +296,20 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal) -> bool {
330296 false
331297 }
332298
333- ty:: TyInfer ( ..) => match infer_is_local {
334- InferIsLocal :: No => false ,
335- InferIsLocal :: Yes |
336- InferIsLocal :: BrokenYes => true
337- } ,
299+ ty:: TyInfer ( ..) => {
300+ infer_is_local. 0
301+ }
302+
303+ ty:: TyAdt ( def, _) => {
304+ def. did . is_local ( )
305+ }
338306
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) ,
307+ ty:: TyForeign ( did) => {
308+ did. is_local ( )
309+ }
341310
342311 ty:: TyDynamic ( ref tt, ..) => {
343- tt. principal ( ) . map_or ( false , |p| {
344- def_id_is_local ( p. def_id ( ) , infer_is_local)
345- } )
312+ tt. principal ( ) . map_or ( false , |p| p. def_id ( ) . is_local ( ) )
346313 }
347314
348315 ty:: TyError => {
0 commit comments