Skip to content

Commit b6303fd

Browse files
committed
Auto merge of rust-lang#139171 - lcnr:coerce-perf, r=<try>
stupid fix for coercion hack perf regression cc rust-lang#136127 rust-lang#138542 r? `@ghost`
2 parents 10a76d6 + e57808d commit b6303fd

File tree

1 file changed

+44
-40
lines changed

1 file changed

+44
-40
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+44-40
Original file line numberDiff line numberDiff line change
@@ -605,48 +605,52 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
605605
// However, we don't want to bail early all the time, since the unholdable obligations
606606
// may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id<This = U>`),
607607
// so we only bail if there (likely) is another way to convert the types.
608-
if !self.infcx.predicate_may_hold(&root_obligation) {
609-
if let Some(dyn_metadata_adt_def_id) = self.tcx.lang_items().get(LangItem::DynMetadata)
610-
&& let Some(metadata_type_def_id) = self.tcx.lang_items().get(LangItem::Metadata)
611-
{
612-
self.probe(|_| {
613-
let ocx = ObligationCtxt::new(&self.infcx);
614-
615-
// returns `true` if `<ty as Pointee>::Metadata` is `DynMetadata<_>`
616-
let has_dyn_trait_metadata = |ty| {
617-
let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty(
618-
&ObligationCause::dummy(),
619-
self.fcx.param_env,
620-
Ty::new_alias(
621-
self.tcx,
622-
ty::AliasTyKind::Projection,
623-
AliasTy::new(self.tcx, metadata_type_def_id, [ty]),
624-
),
625-
);
608+
if let &ty::RawPtr(source_pointee, _) = coerce_source.kind()
609+
&& let &ty::RawPtr(target_pointee, _) = target.kind()
610+
{
611+
if !self.infcx.predicate_may_hold(&root_obligation) {
612+
if let Some(dyn_metadata_adt_def_id) =
613+
self.tcx.lang_items().get(LangItem::DynMetadata)
614+
&& let Some(metadata_type_def_id) =
615+
self.tcx.lang_items().get(LangItem::Metadata)
616+
{
617+
self.probe(|_| {
618+
let ocx = ObligationCtxt::new(&self.infcx);
619+
620+
// returns `true` if `<ty as Pointee>::Metadata` is `DynMetadata<_>`
621+
let has_dyn_trait_metadata = |ty| {
622+
let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty(
623+
&ObligationCause::dummy(),
624+
self.fcx.param_env,
625+
Ty::new_alias(
626+
self.tcx,
627+
ty::AliasTyKind::Projection,
628+
AliasTy::new(self.tcx, metadata_type_def_id, [ty]),
629+
),
630+
);
626631

627-
metadata_ty.is_ok_and(|metadata_ty| {
628-
metadata_ty
629-
.ty_adt_def()
630-
.is_some_and(|d| d.did() == dyn_metadata_adt_def_id)
631-
})
632-
};
633-
634-
// If both types are raw pointers to a (wrapper over a) trait object,
635-
// this might be a cast like `*const W<dyn Trait> -> *const dyn Trait`.
636-
// So it's better to bail and try that. (even if the cast is not possible, for
637-
// example due to vtables not matching, cast diagnostic will likely still be better)
638-
//
639-
// N.B. use `target`, not `coerce_target` (the latter is a var)
640-
if let &ty::RawPtr(source_pointee, _) = coerce_source.kind()
641-
&& let &ty::RawPtr(target_pointee, _) = target.kind()
642-
&& has_dyn_trait_metadata(source_pointee)
643-
&& has_dyn_trait_metadata(target_pointee)
644-
{
645-
return Err(TypeError::Mismatch);
646-
}
632+
metadata_ty.is_ok_and(|metadata_ty| {
633+
metadata_ty
634+
.ty_adt_def()
635+
.is_some_and(|d| d.did() == dyn_metadata_adt_def_id)
636+
})
637+
};
647638

648-
Ok(())
649-
})?;
639+
// If both types are raw pointers to a (wrapper over a) trait object,
640+
// this might be a cast like `*const W<dyn Trait> -> *const dyn Trait`.
641+
// So it's better to bail and try that. (even if the cast is not possible, for
642+
// example due to vtables not matching, cast diagnostic will likely still be better)
643+
//
644+
// N.B. use `target`, not `coerce_target` (the latter is a var)
645+
if has_dyn_trait_metadata(source_pointee)
646+
&& has_dyn_trait_metadata(target_pointee)
647+
{
648+
return Err(TypeError::Mismatch);
649+
}
650+
651+
Ok(())
652+
})?;
653+
}
650654
}
651655
}
652656

0 commit comments

Comments
 (0)