Skip to content

Commit 19ae219

Browse files
committed
Auto merge of rust-lang#138292 - compiler-errors:coercion-fast-path, r=<try>
Use struct tail rather than metadata projection to compute coercion fast path cc rust-lang#136127 (comment) r? `@ghost`
2 parents 2b285cd + 8ff333e commit 19ae219

File tree

1 file changed

+43
-42
lines changed

1 file changed

+43
-42
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+43-42
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rustc_attr_parsing::InlineAttr;
4242
use rustc_errors::codes::*;
4343
use rustc_errors::{Applicability, Diag, struct_span_code_err};
4444
use rustc_hir::def_id::{DefId, LocalDefId};
45-
use rustc_hir::{self as hir, LangItem};
45+
use rustc_hir::{self as hir};
4646
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
4747
use rustc_infer::infer::relate::RelateResult;
4848
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
@@ -56,7 +56,7 @@ use rustc_middle::ty::adjustment::{
5656
};
5757
use rustc_middle::ty::error::TypeError;
5858
use rustc_middle::ty::visit::TypeVisitableExt;
59-
use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt};
59+
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
6060
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
6161
use rustc_trait_selection::infer::InferCtxtExt as _;
6262
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -607,48 +607,49 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
607607
// may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id<This = U>`),
608608
// so we only bail if there (likely) is another way to convert the types.
609609
if !self.infcx.predicate_may_hold(&root_obligation) {
610-
if let Some(dyn_metadata_adt_def_id) = self.tcx.lang_items().get(LangItem::DynMetadata)
611-
&& let Some(metadata_type_def_id) = self.tcx.lang_items().get(LangItem::Metadata)
612-
{
613-
self.probe(|_| {
614-
let ocx = ObligationCtxt::new(&self.infcx);
615-
616-
// returns `true` if `<ty as Pointee>::Metadata` is `DynMetadata<_>`
617-
let has_dyn_trait_metadata = |ty| {
618-
let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty(
619-
&ObligationCause::dummy(),
620-
self.fcx.param_env,
621-
Ty::new_alias(
622-
self.tcx,
623-
ty::AliasTyKind::Projection,
624-
AliasTy::new(self.tcx, metadata_type_def_id, [ty]),
625-
),
626-
);
610+
// FIXME:
611+
if true {
612+
return Err(TypeError::Mismatch);
613+
}
627614

628-
metadata_ty.is_ok_and(|metadata_ty| {
629-
metadata_ty
630-
.ty_adt_def()
631-
.is_some_and(|d| d.did() == dyn_metadata_adt_def_id)
632-
})
633-
};
634-
635-
// If both types are raw pointers to a (wrapper over a) trait object,
636-
// this might be a cast like `*const W<dyn Trait> -> *const dyn Trait`.
637-
// So it's better to bail and try that. (even if the cast is not possible, for
638-
// example due to vtables not matching, cast diagnostic will likely still be better)
639-
//
640-
// N.B. use `target`, not `coerce_target` (the latter is a var)
641-
if let &ty::RawPtr(source_pointee, _) = coerce_source.kind()
642-
&& let &ty::RawPtr(target_pointee, _) = target.kind()
643-
&& has_dyn_trait_metadata(source_pointee)
644-
&& has_dyn_trait_metadata(target_pointee)
645-
{
646-
return Err(TypeError::Mismatch);
647-
}
615+
self.probe(|_| {
616+
let ocx = ObligationCtxt::new(&self.infcx);
617+
618+
// returns `true` if `<ty as Pointee>::Metadata` is `DynMetadata<_>`
619+
let has_dyn_trait_metadata = |ty| {
620+
self.fcx
621+
.tcx
622+
.struct_tail_raw(
623+
ty,
624+
|ty| {
625+
ocx.structurally_normalize_ty(
626+
&ObligationCause::dummy(),
627+
self.fcx.param_env,
628+
ty,
629+
)
630+
.unwrap_or(ty)
631+
},
632+
|| {},
633+
)
634+
.is_trait()
635+
};
636+
637+
// If both types are raw pointers to a (wrapper over a) trait object,
638+
// this might be a cast like `*const W<dyn Trait> -> *const dyn Trait`.
639+
// So it's better to bail and try that. (even if the cast is not possible, for
640+
// example due to vtables not matching, cast diagnostic will likely still be better)
641+
//
642+
// N.B. use `target`, not `coerce_target` (the latter is a var)
643+
if let &ty::RawPtr(source_pointee, _) = coerce_source.kind()
644+
&& let &ty::RawPtr(target_pointee, _) = target.kind()
645+
&& has_dyn_trait_metadata(source_pointee)
646+
&& has_dyn_trait_metadata(target_pointee)
647+
{
648+
return Err(TypeError::Mismatch);
649+
}
648650

649-
Ok(())
650-
})?;
651-
}
651+
Ok(())
652+
})?;
652653
}
653654

654655
// Use a FIFO queue for this custom fulfillment procedure.

0 commit comments

Comments
 (0)