mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Make sure to detect trait upcasting coercion even after normalization
This commit is contained in:
parent
7e66c0b7ed
commit
24eefd08e2
@ -622,7 +622,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
|
||||
)];
|
||||
|
||||
let mut has_unsized_tuple_coercion = false;
|
||||
let mut has_trait_upcasting_coercion = None;
|
||||
|
||||
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
||||
@ -636,22 +635,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
|
||||
if traits.contains(&trait_pred.def_id()) =>
|
||||
{
|
||||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||
if unsize_did == trait_pred.def_id() {
|
||||
let self_ty = trait_pred.self_ty();
|
||||
let unsize_ty = trait_pred.trait_ref.args[1].expect_ty();
|
||||
if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) =
|
||||
(self_ty.kind(), unsize_ty.kind())
|
||||
&& data_a.principal_def_id() != data_b.principal_def_id()
|
||||
{
|
||||
debug!("coerce_unsized: found trait upcasting coercion");
|
||||
has_trait_upcasting_coercion = Some((self_ty, unsize_ty));
|
||||
}
|
||||
if let ty::Tuple(..) = unsize_ty.kind() {
|
||||
debug!("coerce_unsized: found unsized tuple coercion");
|
||||
has_unsized_tuple_coercion = true;
|
||||
}
|
||||
}
|
||||
trait_pred
|
||||
}
|
||||
_ => {
|
||||
@ -659,6 +642,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||
match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) {
|
||||
// Uncertain or unimplemented.
|
||||
Ok(None) => {
|
||||
@ -701,18 +685,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
// be silent, as it causes a type mismatch later.
|
||||
}
|
||||
|
||||
Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()),
|
||||
}
|
||||
}
|
||||
Ok(Some(impl_source)) => {
|
||||
if matches!(impl_source, traits::ImplSource::TraitUpcasting(..)) {
|
||||
has_trait_upcasting_coercion =
|
||||
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
|
||||
}
|
||||
|
||||
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::unsized_tuple_coercion,
|
||||
self.cause.span,
|
||||
"unsized tuple coercion is not stable enough for use and is subject to change",
|
||||
)
|
||||
.emit();
|
||||
queue.extend(impl_source.nested_obligations())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((sub, sup)) = has_trait_upcasting_coercion
|
||||
|
@ -315,7 +315,13 @@ fn rematch_object<'tcx>(
|
||||
// If we're upcasting, get the offset of the vtable pointer, otherwise get
|
||||
// the base of the vtable.
|
||||
Ok(Some(if is_upcasting {
|
||||
ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested })
|
||||
// If source and target trait def ids are identical,
|
||||
// then we are simply removing auto traits.
|
||||
if source_trait_ref.def_id() == target_trait_ref.def_id() {
|
||||
ImplSource::Builtin(nested)
|
||||
} else {
|
||||
ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested })
|
||||
}
|
||||
} else {
|
||||
ImplSource::Object(ImplSourceObjectData { vtable_base, nested })
|
||||
}))
|
||||
|
@ -1,6 +1,8 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
|
||||
trait A {}
|
||||
trait B: A {}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
// check-pass
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
|
||||
pub trait A {}
|
||||
pub trait B: A {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user