Skip to content

Commit 05be0e0

Browse files
author
Lukas Markeffsky
committed
[WIP] check ptr-to-ptr casts via traits
1 parent ef53028 commit 05be0e0

File tree

1 file changed

+31
-7
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+31
-7
lines changed

compiler/rustc_hir_typeck/src/cast.rs

+31-7
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ use super::FnCtxt;
3232

3333
use crate::errors;
3434
use crate::type_error_struct;
35-
use hir::ExprKind;
35+
use hir::{ExprKind, LangItem};
3636
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
3737
use rustc_hir as hir;
38+
use rustc_infer::traits::Obligation;
3839
use rustc_macros::{TypeFoldable, TypeVisitable};
3940
use rustc_middle::mir::Mutability;
4041
use rustc_middle::ty::adjustment::AllowTwoPhase;
@@ -45,7 +46,8 @@ use rustc_session::lint;
4546
use rustc_span::def_id::{DefId, LOCAL_CRATE};
4647
use rustc_span::symbol::sym;
4748
use rustc_span::Span;
48-
use rustc_trait_selection::infer::InferCtxtExt;
49+
use rustc_trait_selection::infer::InferCtxtExt as _;
50+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
4951

5052
/// Reifies a cast check to be checked once we have full type information for
5153
/// a function context.
@@ -724,8 +726,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
724726
Err(CastError::IllegalCast)
725727
}
726728

727-
// ptr -> *
728-
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
729+
// ptr-ptr-cast
730+
(Ptr(m_e), Ptr(m_c)) => {
731+
self.check_ptr_ptr_cast(fcx, m_e, m_c)?;
732+
Ok(CastKind::PtrPtrCast)
733+
}
729734

730735
// ptr-addr-cast
731736
(Ptr(m_expr), Int(t_c)) => {
@@ -770,10 +775,27 @@ impl<'a, 'tcx> CastCheck<'tcx> {
770775
fcx: &FnCtxt<'a, 'tcx>,
771776
m_expr: ty::TypeAndMut<'tcx>,
772777
m_cast: ty::TypeAndMut<'tcx>,
773-
) -> Result<CastKind, CastError> {
778+
) -> Result<(), CastError> {
774779
debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
775780
// ptr-ptr cast. vtables must match.
776781

782+
let meta_did = fcx.tcx.require_lang_item(LangItem::Metadata, Some(self.span));
783+
let expr_meta = Ty::new_projection(fcx.tcx, meta_did, [m_expr.ty]);
784+
let cast_meta = Ty::new_projection(fcx.tcx, meta_did, [m_cast.ty]);
785+
let expr_meta = fcx.normalize(self.span, expr_meta);
786+
let cast_meta = fcx.normalize(self.span, cast_meta);
787+
788+
let pred = ty::TraitRef::from_lang_item(
789+
fcx.tcx,
790+
LangItem::MetadataCast,
791+
self.span,
792+
[expr_meta, cast_meta],
793+
);
794+
let obligation = Obligation::new(fcx.tcx, fcx.misc(self.span), fcx.param_env, pred);
795+
if fcx.predicate_must_hold_modulo_regions(&obligation) {
796+
return Ok(());
797+
}
798+
777799
let expr_kind = fcx.pointer_kind(m_expr.ty, self.span)?;
778800
let cast_kind = fcx.pointer_kind(m_cast.ty, self.span)?;
779801

@@ -784,7 +806,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
784806

785807
// Cast to thin pointer is OK
786808
if cast_kind == PointerKind::Thin {
787-
return Ok(CastKind::PtrPtrCast);
809+
fcx.tcx.dcx().span_err(self.span, format!("{pred}"));
810+
return Ok(());
788811
}
789812

790813
let Some(expr_kind) = expr_kind else {
@@ -799,7 +822,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
799822

800823
// vtable kinds must match
801824
if fcx.tcx.erase_regions(cast_kind) == fcx.tcx.erase_regions(expr_kind) {
802-
Ok(CastKind::PtrPtrCast)
825+
fcx.tcx.dcx().span_err(self.span, format!("{pred}"));
826+
Ok(())
803827
} else {
804828
Err(CastError::DifferingKinds)
805829
}

0 commit comments

Comments
 (0)