Skip to content

Commit 1769c63

Browse files
committed
add a comment and assertion explaining everything
1 parent 9d38541 commit 1769c63

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

src/librustc/traits/coherence.rs

+93-1
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Re
1616
use traits::IntercrateMode;
1717
use traits::select::IntercrateAmbiguityCause;
1818
use ty::{self, Ty, TyCtxt};
19+
use ty::fold::TypeFoldable;
1920
use ty::subst::Subst;
2021

2122
use 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)]
2627
enum 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.
227314
fn 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

Comments
 (0)