Rollup merge of #94242 - compiler-errors:fat-uninhabitable-pointer, r=michaelwoerister
properly handle fat pointers to uninhabitable types Calculate the pointee metadata size by using `tcx.struct_tail_erasing_lifetimes` instead of duplicating the logic in `fat_pointer_kind`. Open to alternatively suggestions on how to fix this. Fixes #94149 r? ````@michaelwoerister```` since you touched this code last, I think!
This commit is contained in:
commit
6b03a46f27
@ -449,7 +449,10 @@ fn pointer_or_reference_metadata<'ll, 'tcx>(
|
||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||
debug_assert_eq!(
|
||||
(thin_pointer_size, thin_pointer_align),
|
||||
cx.size_and_align_of(ptr_type)
|
||||
cx.size_and_align_of(ptr_type),
|
||||
"ptr_type={}, pointee_type={}",
|
||||
ptr_type,
|
||||
pointee_type,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
|
@ -4,9 +4,9 @@
|
||||
use super::CrateDebugContext;
|
||||
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty};
|
||||
use rustc_target::abi::Variants;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::common::CodegenCx;
|
||||
use crate::llvm;
|
||||
@ -63,30 +63,26 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
pointee_ty: Ty<'tcx>,
|
||||
) -> Option<FatPtrKind> {
|
||||
let layout = cx.layout_of(pointee_ty);
|
||||
let pointee_tail_ty = cx.tcx.struct_tail_erasing_lifetimes(pointee_ty, cx.param_env());
|
||||
let layout = cx.layout_of(pointee_tail_ty);
|
||||
trace!(
|
||||
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||
pointee_tail_ty,
|
||||
layout,
|
||||
layout.is_unsized()
|
||||
);
|
||||
|
||||
if !layout.is_unsized() {
|
||||
return None;
|
||||
}
|
||||
|
||||
match *pointee_ty.kind() {
|
||||
match *pointee_tail_ty.kind() {
|
||||
ty::Str | ty::Slice(_) => Some(FatPtrKind::Slice),
|
||||
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
|
||||
ty::Adt(..) | ty::Tuple(..) if matches!(layout.variants, Variants::Single { .. }) => {
|
||||
let last_field_index = layout.fields.count() - 1;
|
||||
debug_assert!(
|
||||
(0..last_field_index)
|
||||
.all(|field_index| { !layout.field(cx, field_index).is_unsized() })
|
||||
);
|
||||
|
||||
let unsized_field = layout.field(cx, last_field_index);
|
||||
debug_assert!(unsized_field.is_unsized());
|
||||
fat_pointer_kind(cx, unsized_field.ty)
|
||||
}
|
||||
ty::Foreign(_) => {
|
||||
// Assert that pointers to foreign types really are thin:
|
||||
debug_assert_eq!(
|
||||
cx.size_of(cx.tcx.mk_imm_ptr(pointee_ty)),
|
||||
cx.size_of(cx.tcx.mk_imm_ptr(pointee_tail_ty)),
|
||||
cx.size_of(cx.tcx.mk_imm_ptr(cx.tcx.types.u8))
|
||||
);
|
||||
None
|
||||
@ -94,7 +90,10 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
||||
_ => {
|
||||
// For all other pointee types we should already have returned None
|
||||
// at the beginning of the function.
|
||||
panic!("fat_pointer_kind() - Encountered unexpected `pointee_ty`: {:?}", pointee_ty)
|
||||
panic!(
|
||||
"fat_pointer_kind() - Encountered unexpected `pointee_tail_ty`: {:?}",
|
||||
pointee_tail_ty
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
// check-pass
|
||||
// compile-flags: -Cdebuginfo=2
|
||||
// fixes issue #94149
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub fn main() {
|
||||
let _ = Foo::<dyn FooTrait>::new();
|
||||
}
|
||||
|
||||
pub struct Foo<T: FooTrait + ?Sized> {
|
||||
base: FooBase,
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T: FooTrait + ?Sized> Foo<T> {
|
||||
pub fn new() -> Box<Foo<T>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FooTrait {}
|
||||
|
||||
pub struct FooBase {
|
||||
cls: Bar,
|
||||
}
|
||||
|
||||
// Bar *must* be a fieldless enum
|
||||
pub enum Bar {}
|
Loading…
Reference in New Issue
Block a user