Skip to content

Commit

Permalink
Consider well-formed predicates in min-specialization
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Mar 15, 2020
1 parent 4377ac3 commit 39ee66a
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 4 deletions.
27 changes: 23 additions & 4 deletions src/librustc_typeck/impl_wf_check/min_specialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
//! in the *unconstrained* substs for `impl2`. A parameter is constrained if
//! its value is completely determined by an associated type projection
//! predicate.
//! 4. Check that all predicates on `impl1` also exist on `impl2` (after
//! matching substs).
//! 4. Check that all predicates on `impl1` either exist on `impl2` (after
//! matching substs), or are well-formed predicates for the trait's type
//! arguments.
//!
//! ## Example
//!
Expand Down Expand Up @@ -129,7 +130,7 @@ fn check_always_applicable(
check_static_lifetimes(tcx, &parent_substs, span);
check_duplicate_params(tcx, impl1_substs, &parent_substs, span);

check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
}
}

Expand Down Expand Up @@ -282,14 +283,17 @@ fn check_static_lifetimes<'tcx>(
/// * on the base `impl impl2`
/// * Currently this check is done using syntactic equality, which is
/// conservative but generally sufficient.
/// * a well-formed predicate of a type argument of the trait being implemented,
/// including the `Self`-type.
fn check_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
infcx: &InferCtxt<'_, 'tcx>,
impl1_def_id: DefId,
impl1_substs: SubstsRef<'tcx>,
impl2_node: Node,
impl2_substs: SubstsRef<'tcx>,
span: Span,
) {
let tcx = infcx.tcx;
let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
let mut impl2_predicates = if impl2_node.is_from_trait() {
// Always applicable traits have to be always applicable without any
Expand Down Expand Up @@ -329,6 +333,21 @@ fn check_predicates<'tcx>(
})
.copied()
.collect();

// Include the well-formed predicates of the type parameters of the impl.
for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() {
if let Some(obligations) = wf::obligations(
infcx,
tcx.param_env(impl1_def_id),
tcx.hir().as_local_hir_id(impl1_def_id).unwrap(),
ty,
span,
) {
impl2_predicates
.predicates
.extend(obligations.into_iter().map(|obligation| obligation.predicate))
}
}
impl2_predicates.predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));

for predicate in impl1_predicates.predicates {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Test that specializing on the well-formed predicates of the trait and
// self-type of an impl is allowed.

// check-pass

#![feature(min_specialization)]

struct OrdOnly<T: Ord>(T);

trait SpecTrait<U> {
fn f();
}

impl<T, U> SpecTrait<U> for T {
default fn f() {}
}

impl<T: Ord> SpecTrait<()> for OrdOnly<T> {
fn f() {}
}

impl<T: Ord> SpecTrait<OrdOnly<T>> for () {
fn f() {}
}

impl<T: Ord, U: Ord, V: Ord> SpecTrait<(OrdOnly<T>, OrdOnly<U>)> for &[OrdOnly<V>] {
fn f() {}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Test that supertraits can't be assumed in impls of
// `rustc_specialization_trait`, as such impls would
// allow specializing on the supertrait.

#![feature(min_specialization)]
#![feature(rustc_attrs)]

#[rustc_specialization_trait]
trait SpecMarker: Default {
fn f();
}

impl<T: Default> SpecMarker for T {
//~^ ERROR cannot specialize
fn f() {}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: cannot specialize on trait `std::default::Default`
--> $DIR/specialization_super_trait.rs:13:1
|
LL | / impl<T: Default> SpecMarker for T {
LL | |
LL | | fn f() {}
LL | | }
| |_^

error: aborting due to previous error

0 comments on commit 39ee66a

Please sign in to comment.