mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 02:33:55 +00:00
Normalize consistently for specializations
This commit is contained in:
parent
bd928a0b5e
commit
fafe9e71d5
@ -99,14 +99,13 @@ pub fn translate_substs<'tcx>(
|
|||||||
return source_substs;
|
return source_substs;
|
||||||
}
|
}
|
||||||
|
|
||||||
fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
|
fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl)
|
||||||
|()| {
|
.unwrap_or_else(|()| {
|
||||||
bug!(
|
bug!(
|
||||||
"When translating substitutions from {source_impl:?} to {target_impl:?}, \
|
"When translating substitutions from {source_impl:?} to {target_impl:?}, \
|
||||||
the expected specialization failed to hold"
|
the expected specialization failed to hold"
|
||||||
)
|
)
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
specialization_graph::Node::Trait(..) => source_trait_ref.substs,
|
specialization_graph::Node::Trait(..) => source_trait_ref.substs,
|
||||||
};
|
};
|
||||||
@ -153,20 +152,9 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
|
|||||||
|
|
||||||
// Create an infcx, taking the predicates of impl1 as assumptions:
|
// Create an infcx, taking the predicates of impl1 as assumptions:
|
||||||
let infcx = tcx.infer_ctxt().build();
|
let infcx = tcx.infer_ctxt().build();
|
||||||
let impl1_trait_ref =
|
|
||||||
match traits::fully_normalize(&infcx, ObligationCause::dummy(), penv, impl1_trait_ref) {
|
|
||||||
Ok(impl1_trait_ref) => impl1_trait_ref,
|
|
||||||
Err(_errors) => {
|
|
||||||
tcx.sess.delay_span_bug(
|
|
||||||
tcx.def_span(impl1_def_id),
|
|
||||||
format!("failed to fully normalize {impl1_trait_ref}"),
|
|
||||||
);
|
|
||||||
impl1_trait_ref
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attempt to prove that impl2 applies, given all of the above.
|
// Attempt to prove that impl2 applies, given all of the above.
|
||||||
fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
|
fulfill_implication(&infcx, penv, impl1_trait_ref, impl1_def_id, impl2_def_id).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to fulfill all obligations of `target_impl` after unification with
|
/// Attempt to fulfill all obligations of `target_impl` after unification with
|
||||||
@ -178,6 +166,7 @@ fn fulfill_implication<'tcx>(
|
|||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
source_trait_ref: ty::TraitRef<'tcx>,
|
source_trait_ref: ty::TraitRef<'tcx>,
|
||||||
|
source_impl: DefId,
|
||||||
target_impl: DefId,
|
target_impl: DefId,
|
||||||
) -> Result<SubstsRef<'tcx>, ()> {
|
) -> Result<SubstsRef<'tcx>, ()> {
|
||||||
debug!(
|
debug!(
|
||||||
@ -185,6 +174,22 @@ fn fulfill_implication<'tcx>(
|
|||||||
param_env, source_trait_ref, target_impl
|
param_env, source_trait_ref, target_impl
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let source_trait_ref = match traits::fully_normalize(
|
||||||
|
&infcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
|
source_trait_ref,
|
||||||
|
) {
|
||||||
|
Ok(source_trait_ref) => source_trait_ref,
|
||||||
|
Err(_errors) => {
|
||||||
|
infcx.tcx.sess.delay_span_bug(
|
||||||
|
infcx.tcx.def_span(source_impl),
|
||||||
|
format!("failed to fully normalize {source_trait_ref}"),
|
||||||
|
);
|
||||||
|
source_trait_ref
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_trait = ImplSubject::Trait(source_trait_ref);
|
let source_trait = ImplSubject::Trait(source_trait_ref);
|
||||||
|
|
||||||
let selcx = &mut SelectionContext::new(&infcx);
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
@ -194,7 +199,7 @@ fn fulfill_implication<'tcx>(
|
|||||||
|
|
||||||
// do the impls unify? If not, no specialization.
|
// do the impls unify? If not, no specialization.
|
||||||
let Ok(InferOk { obligations: more_obligations, .. }) =
|
let Ok(InferOk { obligations: more_obligations, .. }) =
|
||||||
infcx.at(&ObligationCause::dummy(), param_env, ).eq(DefineOpaqueTypes::No,source_trait, target_trait)
|
infcx.at(&ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, source_trait, target_trait)
|
||||||
else {
|
else {
|
||||||
debug!(
|
debug!(
|
||||||
"fulfill_implication: {:?} does not unify with {:?}",
|
"fulfill_implication: {:?} does not unify with {:?}",
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
// Another regression test for #109815.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
#[rustc_specialization_trait]
|
||||||
|
trait X {}
|
||||||
|
trait Z {
|
||||||
|
type Assoc: X;
|
||||||
|
}
|
||||||
|
struct A<T>(T);
|
||||||
|
|
||||||
|
impl X for () {}
|
||||||
|
|
||||||
|
impl<T: X> Z for A<T> {
|
||||||
|
type Assoc = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
trait MyFrom<T> {
|
||||||
|
fn from(other: T) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MyFrom<()> for T {
|
||||||
|
default fn from(other: ()) -> T {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: X> MyFrom<<A<T> as Z>::Assoc> for T {
|
||||||
|
fn from(other: ()) -> T {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,33 @@
|
|||||||
|
// A regression test for #109815.
|
||||||
|
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
#[rustc_specialization_trait]
|
||||||
|
trait X {}
|
||||||
|
trait Y: X {}
|
||||||
|
trait Z {
|
||||||
|
type Assoc: Y;
|
||||||
|
}
|
||||||
|
struct A<T>(T);
|
||||||
|
|
||||||
|
impl<T: X> Z for A<T> {}
|
||||||
|
//~^ ERROR not all trait items implemented
|
||||||
|
|
||||||
|
trait MyFrom<T> {
|
||||||
|
fn from(other: T) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MyFrom<T> for T {
|
||||||
|
default fn from(other: T) -> T {
|
||||||
|
other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: X> MyFrom<<A<T> as Z>::Assoc> for T {
|
||||||
|
fn from(other: <A<T> as Z>::Assoc) -> T {
|
||||||
|
other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0046]: not all trait items implemented, missing: `Assoc`
|
||||||
|
--> $DIR/specialize_on_type_error.rs:14:1
|
||||||
|
|
|
||||||
|
LL | type Assoc: Y;
|
||||||
|
| ------------- `Assoc` from trait
|
||||||
|
...
|
||||||
|
LL | impl<T: X> Z for A<T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0046`.
|
Loading…
Reference in New Issue
Block a user