Consider well-formed predicates in min-specialization
This commit is contained in:
parent
4377ac3e2f
commit
39ee66ab82
@ -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
|
||||
//!
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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 {
|
||||
|
@ -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() {}
|
@ -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() {}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user