@@ -16,13 +16,14 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Re
1616use traits:: IntercrateMode ;
1717use traits:: select:: IntercrateAmbiguityCause ;
1818use ty:: { self , Ty , TyCtxt } ;
19+ use ty:: fold:: TypeFoldable ;
1920use ty:: subst:: Subst ;
2021
2122use infer:: { InferCtxt , InferOk } ;
2223
23- #[ derive( Copy , Clone , Debug ) ]
2424/// Whether we do the orphan check relative to this crate or
2525/// to some remote crate.
26+ #[ derive( Copy , Clone , Debug ) ]
2627enum InCrate {
2728 Local ,
2829 Remote
@@ -224,6 +225,92 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
224225 orphan_check_trait_ref ( tcx, trait_ref, InCrate :: Local )
225226}
226227
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.
227314fn orphan_check_trait_ref < ' tcx > ( tcx : TyCtxt ,
228315 trait_ref : ty:: TraitRef < ' tcx > ,
229316 in_crate : InCrate )
@@ -232,6 +319,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
232319 debug ! ( "orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})" ,
233320 trait_ref, in_crate) ;
234321
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+
235327 // First, create an ordered iterator over all the type parameters to the trait, with the self
236328 // type appearing first.
237329 // Find the first input type that either references a type parameter OR
0 commit comments