Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Next Next commit
Implement the re-rebalance coherence rfc
  • Loading branch information
weiznich committed Jan 3, 2019
commit 757d7ba9c9e66320f8ff22d435ad30d6048585e1
125 changes: 95 additions & 30 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,43 +371,108 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt<'_, '_, '_>,
trait_ref);
}

// First, create an ordered iterator over all the type parameters to the trait, with the self
// type appearing first.
// Find the first input type that either references a type parameter OR
// some local type.
for input_ty in trait_ref.input_types() {
if ty_is_local(tcx, input_ty, in_crate) {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);

// First local input type. Check that there are no
// uncovered type parameters.
let uncovered_tys = uncovered_tys(tcx, input_ty, in_crate);
for uncovered_ty in uncovered_tys {
if let Some(param) = uncovered_ty.walk()
.find(|t| is_possibly_remote_type(t, in_crate))
{
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
return Err(OrphanCheckErr::UncoveredTy(param));
if tcx.features().re_rebalance_coherence {
// Given impl<P1..=Pn> Trait<T1..=Tn> for T0, an impl is valid only
// if at least one of the following is true:
//
// - Trait is a local trait
// (already checked in orphan_check prior to calling this function)
// - All of
// - At least one of the types T0..=Tn must be a local type.
// Let Ti be the first such type.
// - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
//
for input_ty in trait_ref.input_types() {
debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
if ty_is_local(tcx, input_ty, in_crate) {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
return Ok(());
} else if is_uncovered_ty(input_ty) {
debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
return Err(OrphanCheckErr::UncoveredTy(input_ty))
}
}
// If we exit above loop, never found a local type.
debug!("orphan_check_trait_ref: no local type");
Err(OrphanCheckErr::NoLocalInputType)
} else {
// First, create an ordered iterator over all the type parameters to the trait, with the self
// type appearing first.
// Find the first input type that either references a type parameter OR
// some local type.
for input_ty in trait_ref.input_types() {
if ty_is_local(tcx, input_ty, in_crate) {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);

// First local input type. Check that there are no
// uncovered type parameters.
let uncovered_tys = uncovered_tys(tcx, input_ty, in_crate);
for uncovered_ty in uncovered_tys {
if let Some(param) = uncovered_ty.walk()
.find(|t| is_possibly_remote_type(t, in_crate))
{
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
return Err(OrphanCheckErr::UncoveredTy(param));
}
}

// OK, found local type, all prior types upheld invariant.
return Ok(());
}

// OK, found local type, all prior types upheld invariant.
return Ok(());
// Otherwise, enforce invariant that there are no type
// parameters reachable.
if let Some(param) = input_ty.walk()
.find(|t| is_possibly_remote_type(t, in_crate))
{
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
return Err(OrphanCheckErr::UncoveredTy(param));
}
}
// If we exit above loop, never found a local type.
debug!("orphan_check_trait_ref: no local type");
Err(OrphanCheckErr::NoLocalInputType)
}
}

fn is_uncovered_ty(ty: Ty<'_>) -> bool {
match ty.sty {
ty::Bool |
ty::Char |
ty::Int(..) |
ty::Uint(..) |
ty::Float(..) |
ty::Str |
ty::FnDef(..) |
ty::FnPtr(_) |
ty::Array(..) |
ty::Slice(..) |
ty::RawPtr(..) |
ty::Ref(..) |
ty::Never |
ty::Tuple(..) |
ty::Bound(..) |
ty::Infer(..) |
ty::Adt(..) |
ty::Foreign(..) |
ty::Dynamic(..) |
ty::Error |
ty::Projection(..) => {
false
}

ty::Param(..) => {
true
}

// Otherwise, enforce invariant that there are no type
// parameters reachable.
if let Some(param) = input_ty.walk()
.find(|t| is_possibly_remote_type(t, in_crate))
{
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
return Err(OrphanCheckErr::UncoveredTy(param));
ty::UnnormalizedProjection(..) |
ty::Closure(..) |
ty::Generator(..) |
ty::GeneratorWitness(..) |
ty::Opaque(..) => {
bug!("is_uncovered_ty invoked on unexpected type: {:?}", ty)
}
}

// If we exit above loop, never found a local type.
debug!("orphan_check_trait_ref: no local type");
return Err(OrphanCheckErr::NoLocalInputType);
}

fn uncovered_tys<'tcx>(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>, in_crate: InCrate)
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,9 @@ declare_features! (

// Allows paths to enum variants on type aliases.
(active, type_alias_enum_variants, "1.31.0", Some(49683), None),

// Re-Rebalance coherence
(active, re_rebalance_coherence, "1.32.0", Some(55437), None),
);

declare_features! (
Expand Down