From c73a2f8a652134bd7bf00ca61ca65bd7adb8aec7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 23 Feb 2022 08:11:50 -0800 Subject: [PATCH] properly handle fat pointers to uninhabitable types --- .../src/debuginfo/metadata.rs | 5 ++- .../rustc_codegen_llvm/src/debuginfo/utils.rs | 33 +++++++++---------- ...uginfo-emit-llvm-ir-and-split-debuginfo.rs | 0 ...fo_with_uninhabitable_field_and_unsized.rs | 29 ++++++++++++++++ 4 files changed, 49 insertions(+), 18 deletions(-) rename src/test/ui/{ => debuginfo}/debuginfo-emit-llvm-ir-and-split-debuginfo.rs (100%) create mode 100644 src/test/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index ef87b7b1a7e07..517c539b45ac8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -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 { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index acd032a7dc6d0..fa75463067f47 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -4,9 +4,9 @@ use super::namespace::item_namespace; 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 { - 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 + ) } } } diff --git a/src/test/ui/debuginfo-emit-llvm-ir-and-split-debuginfo.rs b/src/test/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs similarity index 100% rename from src/test/ui/debuginfo-emit-llvm-ir-and-split-debuginfo.rs rename to src/test/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs diff --git a/src/test/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs b/src/test/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs new file mode 100644 index 0000000000000..833a4726acb0f --- /dev/null +++ b/src/test/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: -Cdebuginfo=2 +// fixes issue #94149 + +#![allow(dead_code)] + +pub fn main() { + let _ = Foo::::new(); +} + +pub struct Foo { + base: FooBase, + value: T, +} + +impl Foo { + pub fn new() -> Box> { + todo!() + } +} + +pub trait FooTrait {} + +pub struct FooBase { + cls: Bar, +} + +// Bar *must* be a fieldless enum +pub enum Bar {}