@@ -16,13 +16,14 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Re
16
16
use traits:: IntercrateMode ;
17
17
use traits:: select:: IntercrateAmbiguityCause ;
18
18
use ty:: { self , Ty , TyCtxt } ;
19
+ use ty:: fold:: TypeFoldable ;
19
20
use ty:: subst:: Subst ;
20
21
21
22
use infer:: { InferCtxt , InferOk } ;
22
23
23
- #[ derive( Copy , Clone , Debug ) ]
24
24
/// Whether we do the orphan check relative to this crate or
25
25
/// to some remote crate.
26
+ #[ derive( Copy , Clone , Debug ) ]
26
27
enum InCrate {
27
28
Local ,
28
29
Remote
@@ -224,6 +225,92 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
224
225
orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local )
225
226
}
226
227
228
+ /// Check whether a trait-ref is potentially implementable by a crate.
229
+ ///
230
+ /// The current rule is that a trait-ref orphan checks in a crate C:
231
+ ///
232
+ /// 1. Order the parameters in the trait-ref in subst order - Self first,
233
+ /// others linearly (e.g. `<U as Foo<V, W>>` is U < V < W).
234
+ /// 2. Of these type parameters, there is at least one type parameter
235
+ /// in which, walking the type as a tree, you can reach a type local
236
+ /// to C where all types in-between are fundamental types. Call the
237
+ /// first such parameter the "local key parameter".
238
+ /// - e.g. `Box<LocalType>` is OK, because you can visit LocalType
239
+ /// going through `Box`, which is fundamental.
240
+ /// - similarly, `FundamentalPair<Vec<()>, Box<LocalType>>` is OK for
241
+ /// the same reason.
242
+ /// - but (knowing that `Vec<T>` is non-fundamental, and assuming it's
243
+ /// not local), `Vec<LocalType>` is bad, because `Vec<->` is between
244
+ /// the local type and the type parameter.
245
+ /// 3. Every type parameter before the local key parameter is fully known in C.
246
+ /// - e.g. `impl<T> T: Trait<LocalType>` is bad, because `T` might be
247
+ /// an unknown type.
248
+ /// - but `impl<T> LocalType: Trait<T>` is OK, because `LocalType`
249
+ /// occurs before `T`.
250
+ /// 4. Every type in the local key parameter not known in C, going
251
+ /// through the parameter's type tree, must appear only as a subtree of
252
+ /// a type local to C, with only fundamental types between the type
253
+ /// local to C and the local key parameter.
254
+ /// - e.g. `Vec<LocalType<T>>>` (or equivalently `Box<Vec<LocalType<T>>>`)
255
+ /// is bad, because the only local type with `T` as a subtree is
256
+ /// `LocalType<T>`, and `Vec<->` is between it and the type parameter.
257
+ /// - similarly, `FundamentalPair<LocalType<T>, T>` is bad, because
258
+ /// the second occurence of `T` is not a subtree of *any* local type.
259
+ /// - however, `LocalType<Vec<T>>` is OK, because `T` is a subtree of
260
+ /// `LocalType<Vec<T>>`, which is local and has no types between it and
261
+ /// the type parameter.
262
+ ///
263
+ /// The orphan rules actually serve several different purposes:
264
+ ///
265
+ /// 1. They enable link-safety - i.e. 2 mutually-unknowing crates (where
266
+ /// every type local to one crate is unknown in the other) can't implement
267
+ /// the same trait-ref. This follows because it can be seen that no such
268
+ /// type can orphan-check in 2 such crates.
269
+ ///
270
+ /// To check that a local impl follows the orphan rules, we check it in
271
+ /// InCrate::Local mode, using type parameters for the "generic" types.
272
+ ///
273
+ /// 2. They ground negative reasoning for coherence. If a user wants to
274
+ /// write both a conditional blanket impl and a specific impl, we need to
275
+ /// make sure they do not overlap. For example, if we write
276
+ /// ```
277
+ /// impl<T> IntoIterator for Vec<T>
278
+ /// impl<T: Iterator> IntoIterator for T
279
+ /// ```
280
+ /// We need to be able to prove that `Option<$0>: !Iterator` for every type $0.
281
+ /// We can observe that this holds in the current crate, but we need to make
282
+ /// sure this will also hold in all unknown crates (both "independent" crates,
283
+ /// which we need for link-safety, and also child crates, because we don't want
284
+ /// child crates to get error for impl conflicts in a *dependency*).
285
+ ///
286
+ /// For that, we only allow negative reasoning if, for every assignment to the
287
+ /// inference variables, every unknown crate would get an orphan error if they
288
+ /// try to implement this trait-ref. To check for this, we use InCrate::Remote
289
+ /// mode. That is sound because we already know all the impls from known crates.
290
+ ///
291
+ /// 3. For non-#[fundamental] traits, they guarantee that parent crates can
292
+ /// add "non-blanket" impls without breaking negative reasoning in dependent
293
+ /// crates. This is the "rebalancing coherence" (RFC 1023) restriction.
294
+ ///
295
+ /// For that, we only a allow crate to perform negative reasoning on
296
+ /// non-local-non-#[fundamental] only if there's a local key parameter as per (2).
297
+ ///
298
+ /// Because we never perform negative reasoning generically (coherence does
299
+ /// not involve type parameters), this can be interpreted as doing the full
300
+ /// orphan check (using InCrate::Local mode), substituting non-local known
301
+ /// types for all inference variables.
302
+ ///
303
+ /// This allows for crates to future-compatibly add impls as long as they
304
+ /// can't apply to types with a key parameter in a child crate - applying
305
+ /// the rules, this basically means that every type parameter in the impl
306
+ /// must appear behind a non-fundamental type (because this is not a
307
+ /// type-system requirement, crate owners might also go for "semantic
308
+ /// future-compatibility" involving things such as sealed traits, but
309
+ /// the above requirement is sufficient, and is necessary in "open world"
310
+ /// cases).
311
+ ///
312
+ /// Note that this function is never called for types that have both type
313
+ /// parameters and inference variables.
227
314
fn orphan_check_trait_ref < ' tcx > ( tcx : TyCtxt ,
228
315
trait_ref : ty:: TraitRef < ' tcx > ,
229
316
in_crate : InCrate )
@@ -232,6 +319,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
232
319
debug ! ( "orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})" ,
233
320
trait_ref, in_crate) ;
234
321
322
+ if trait_ref. needs_infer ( ) && trait_ref. needs_subst ( ) {
323
+ bug ! ( "can't orphan check a trait ref with both params and inference variables {:?}" ,
324
+ trait_ref) ;
325
+ }
326
+
235
327
// First, create an ordered iterator over all the type parameters to the trait, with the self
236
328
// type appearing first.
237
329
// Find the first input type that either references a type parameter OR
0 commit comments