@@ -19,18 +19,8 @@ use ty::subst::Subst;
19
19
20
20
use infer:: { InferCtxt , InferOk } ;
21
21
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 ) ;
34
24
35
25
pub struct OverlapResult < ' tcx > {
36
26
pub impl_header : ty:: ImplHeader < ' tcx > ,
@@ -136,46 +126,32 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
136
126
}
137
127
138
128
pub 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
142
130
{
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) ;
155
132
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 ( ) {
173
136
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 ;
178
146
}
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 ( )
179
155
}
180
156
181
157
pub 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>,
213
189
return Ok ( ( ) ) ;
214
190
}
215
191
216
- orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal :: No )
192
+ orphan_check_trait_ref ( tcx, trait_ref, InferIsLocal ( false ) )
217
193
}
218
194
219
195
fn orphan_check_trait_ref < ' tcx > ( tcx : TyCtxt ,
220
196
trait_ref : ty:: TraitRef < ' tcx > ,
221
197
infer_is_local : InferIsLocal )
222
198
-> Result < ( ) , OrphanCheckErr < ' tcx > >
223
199
{
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 ) ;
226
202
227
203
// First, create an ordered iterator over all the type parameters to the trait, with the self
228
204
// type appearing first.
@@ -236,9 +212,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
236
212
// uncovered type parameters.
237
213
let uncovered_tys = uncovered_tys ( tcx, input_ty, infer_is_local) ;
238
214
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) ) {
242
216
debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
243
217
return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
244
218
}
@@ -250,11 +224,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
250
224
251
225
// Otherwise, enforce invariant that there are no type
252
226
// 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
+ }
258
232
}
259
233
}
260
234
@@ -276,7 +250,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
276
250
}
277
251
}
278
252
279
- fn is_possibly_remote_type ( ty : Ty , _infer_is_local : InferIsLocal ) -> bool {
253
+ fn is_type_parameter ( ty : Ty ) -> bool {
280
254
match ty. sty {
281
255
ty:: TyProjection ( ..) | ty:: TyParam ( ..) => true ,
282
256
_ => false ,
@@ -299,15 +273,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
299
273
}
300
274
}
301
275
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 {
311
277
debug ! ( "ty_is_local_constructor({:?})" , ty) ;
312
278
313
279
match ty. sty {
@@ -330,19 +296,20 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal) -> bool {
330
296
false
331
297
}
332
298
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
+ }
338
306
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
+ }
341
310
342
311
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 ( ) )
346
313
}
347
314
348
315
ty:: TyError => {
0 commit comments