Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions compiler/rustc_codegen_llvm/src/gotoc/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::cbmc::goto_program::{BuiltinFn, Expr, Location, Stmt, Symbol, Type};
use super::cbmc::utils::{aggr_name, BUG_REPORT_URL};
use super::cbmc::MachineModel;
use super::metadata::*;
use super::typ::{is_dyn_trait_fat_pointer, is_pointer, pointee_type};
use super::typ::{is_pointer, pointee_type};
use super::utils::{dynamic_fat_ptr, slice_fat_ptr};
use crate::btree_string_map;
use num::bigint::BigInt;
Expand Down Expand Up @@ -679,15 +679,18 @@ impl<'tcx> GotocCtx<'tcx> {
) -> Option<Expr> {
// Check if the cast is from a vtable fat pointer to another
// vtable fat pointer (which can happen with auto trait fat pointers)
if is_dyn_trait_fat_pointer(src_mir_type) {
if self.is_vtable_fat_pointer(src_mir_type) {
self.cast_unsized_dyn_trait_to_unsized_dyn_trait(
src_goto_expr.clone(),
src_mir_type,
dst_mir_type,
)
} else {
// Assert that the source is not a pointer or is a thin pointer
assert!(pointee_type(src_mir_type).map_or(true, |p| self.use_thin_pointer(p)));
// Check that the source is either not a pointer, or a thin or a slice pointer
assert!(
pointee_type(src_mir_type)
.map_or(true, |p| self.use_thin_pointer(p) || self.use_slice_fat_pointer(p))
);

// Sized to unsized cast
self.cast_sized_expr_to_unsized_expr(src_goto_expr.clone(), src_mir_type, dst_mir_type)
Expand Down Expand Up @@ -923,8 +926,8 @@ impl<'tcx> GotocCtx<'tcx> {
}

// The source destination must be a fat pointers to a dyn trait object
assert!(is_dyn_trait_fat_pointer(src_mir_type));
assert!(is_dyn_trait_fat_pointer(dst_mir_type));
assert!(self.is_vtable_fat_pointer(src_mir_type));
assert!(self.is_vtable_fat_pointer(dst_mir_type));

let dst_mir_dyn_ty = pointee_type(dst_mir_type).unwrap();

Expand Down Expand Up @@ -965,7 +968,7 @@ impl<'tcx> GotocCtx<'tcx> {

// The src type cannot be a pointer to a dynamic trait object, otherwise
// we should have called cast_unsized_dyn_trait_to_unsized_dyn_trait
assert!(!is_dyn_trait_fat_pointer(src_mir_type));
assert!(!self.is_vtable_fat_pointer(src_mir_type));

match (src_mir_type.kind(), dst_mir_type.kind()) {
(ty::Ref(..), ty::Ref(..)) => {
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_codegen_llvm/src/gotoc/typ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,11 +1016,6 @@ pub fn pointee_type(pointer_type: Ty<'tcx>) -> Option<Ty<'tcx>> {
}
}

/// Check if the mir type already is a vtable fat pointer.
pub fn is_dyn_trait_fat_pointer(mir_type: Ty<'tcx>) -> bool {
if let Some(p) = pointee_type(mir_type) { p.is_trait() } else { false }
}

impl<'tcx> GotocCtx<'tcx> {
/// A pointer to the mir type should be a thin pointer.
pub fn use_thin_pointer(&self, mir_type: Ty<'tcx>) -> bool {
Expand All @@ -1037,4 +1032,9 @@ impl<'tcx> GotocCtx<'tcx> {
let metadata = mir_type.ptr_metadata_ty(self.tcx);
return metadata != self.tcx.types.unit && metadata != self.tcx.types.usize;
}

/// Check if the mir type already is a vtable fat pointer.
pub fn is_vtable_fat_pointer(&self, mir_type: Ty<'tcx>) -> bool {
pointee_type(mir_type).map_or(false, |p| self.use_vtable_fat_pointer(p))
}
}