mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
implement debuginfo for unsafe binders
This commit is contained in:
@@ -480,8 +480,7 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
|
||||
},
|
||||
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
|
||||
ty::Pat(base, _) => return type_di_node(cx, base),
|
||||
// FIXME(unsafe_binders): impl debug info
|
||||
ty::UnsafeBinder(_) => unimplemented!(),
|
||||
ty::UnsafeBinder(_) => build_unsafe_binder_type_di_node(cx, t, unique_type_id),
|
||||
ty::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Bound(..)
|
||||
@@ -1488,6 +1487,56 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
|
||||
.di_node
|
||||
}
|
||||
|
||||
/// Creates the debuginfo node for `unsafe<'a> T` binder types.
|
||||
///
|
||||
/// We treat an unsafe binder like a struct with a single field named `inner`
|
||||
/// rather than delegating to the inner type's DI node directly. This way the
|
||||
/// debugger shows the binder's own type name, and the wrapped value is still
|
||||
/// accessible through the `inner` field.
|
||||
fn build_unsafe_binder_type_di_node<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
binder_type: Ty<'tcx>,
|
||||
unique_type_id: UniqueTypeId<'tcx>,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
let ty::UnsafeBinder(inner) = binder_type.kind() else {
|
||||
bug!(
|
||||
"Only ty::UnsafeBinder is valid for build_unsafe_binder_type_di_node. Found {:?} instead.",
|
||||
binder_type
|
||||
)
|
||||
};
|
||||
let inner_type = inner.skip_binder();
|
||||
let inner_type_di_node = type_di_node(cx, inner_type);
|
||||
|
||||
let type_name = compute_debuginfo_type_name(cx.tcx, binder_type, true);
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
type_map::stub(
|
||||
cx,
|
||||
Stub::Struct,
|
||||
unique_type_id,
|
||||
&type_name,
|
||||
None,
|
||||
cx.size_and_align_of(binder_type),
|
||||
NO_SCOPE_METADATA,
|
||||
DIFlags::FlagZero,
|
||||
),
|
||||
|cx, unsafe_binder_type_di_node| {
|
||||
let inner_layout = cx.layout_of(inner_type);
|
||||
smallvec![build_field_di_node(
|
||||
cx,
|
||||
unsafe_binder_type_di_node,
|
||||
"inner",
|
||||
inner_layout,
|
||||
Size::ZERO,
|
||||
DIFlags::FlagZero,
|
||||
inner_type_di_node,
|
||||
None,
|
||||
)]
|
||||
},
|
||||
NO_GENERICS,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the global variable for the vtable.
|
||||
///
|
||||
/// When using global variables, we may have created an addrspacecast to get a pointer to the
|
||||
|
||||
@@ -430,7 +430,19 @@ fn push_debuginfo_type_name<'tcx>(
|
||||
push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited);
|
||||
}
|
||||
}
|
||||
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binders)"),
|
||||
ty::UnsafeBinder(inner) => {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("unsafe$<");
|
||||
} else {
|
||||
output.push_str("unsafe ");
|
||||
}
|
||||
|
||||
push_debuginfo_type_name(tcx, inner.skip_binder(), qualified, output, visited);
|
||||
|
||||
if cpp_like_debuginfo {
|
||||
push_close_angle_bracket(cpp_like_debuginfo, output);
|
||||
}
|
||||
}
|
||||
ty::Param(_)
|
||||
| ty::Error(_)
|
||||
| ty::Infer(_)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//@ compile-flags: -g
|
||||
//@ disable-gdb-pretty-printers
|
||||
//@ ignore-backends: gcc
|
||||
|
||||
// Tests that debuginfo is correctly generated for `unsafe<'a> T` binder types.
|
||||
|
||||
// === GDB TESTS ===================================================================================
|
||||
|
||||
//@ gdb-command:run
|
||||
|
||||
//@ gdb-command:whatis binder_i32
|
||||
//@ gdb-check:type = unsafe &i32
|
||||
|
||||
//@ gdb-command:print unwrapped_i32
|
||||
//@ gdb-check:$1 = 67
|
||||
|
||||
//@ gdb-command:whatis no_lifetime
|
||||
//@ gdb-check:type = unsafe i32
|
||||
|
||||
//@ gdb-command:whatis unsafe_binder_tuple
|
||||
//@ gdb-check:type = unsafe (&i32, &i32)
|
||||
|
||||
//@ gdb-command:whatis binder_tuple_ref
|
||||
//@ gdb-check:type = (&i32, &i32)
|
||||
|
||||
//@ gdb-command:whatis binder.inner
|
||||
//@ gdb-check:type = unsafe &i32
|
||||
|
||||
//@ gdb-command:print wrapper.val
|
||||
//@ gdb-check:$2 = 99
|
||||
|
||||
//@ gdb-command:whatis binder_raw
|
||||
//@ gdb-check:type = unsafe *const i32
|
||||
|
||||
//@ gdb-command:print binder_raw_val
|
||||
//@ gdb-check:$3 = 7
|
||||
|
||||
#![feature(unsafe_binders)]
|
||||
#[expect(incomplete_features)]
|
||||
|
||||
use std::unsafe_binder::{unwrap_binder, wrap_binder};
|
||||
|
||||
struct Wrapper {
|
||||
val: i32,
|
||||
}
|
||||
|
||||
struct Binder {
|
||||
inner: unsafe<'a> &'a i32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 67i32;
|
||||
let binder_i32: unsafe<'a> &'a i32 = unsafe { wrap_binder!(&x) };
|
||||
let unwrapped_i32: i32 = unsafe { *unwrap_binder!(binder_i32) };
|
||||
|
||||
let y = 123i32;
|
||||
let no_lifetime: unsafe<> i32 = unsafe { wrap_binder!(y) };
|
||||
|
||||
let unsafe_binder_tuple: unsafe<'a> (&'a i32, &'a i32) = unsafe {
|
||||
wrap_binder!((&114i32, &514i32))
|
||||
};
|
||||
let binder_tuple_ref: (&i32, &i32) = unsafe { unwrap_binder!(unsafe_binder_tuple) };
|
||||
|
||||
let val = 99i32;
|
||||
let binder = Binder { inner: unsafe { wrap_binder!(&val) } };
|
||||
let wrapper = Wrapper { val: unsafe { *unwrap_binder!(binder.inner) } };
|
||||
|
||||
let z = 7i32;
|
||||
let raw: *const i32 = &z;
|
||||
let binder_raw: unsafe<'a> *const i32 = unsafe { wrap_binder!(raw) };
|
||||
let binder_raw_val: i32 = unsafe { *unwrap_binder!(binder_raw) };
|
||||
|
||||
gugugaga(); // #break
|
||||
}
|
||||
|
||||
fn gugugaga() { () }
|
||||
@@ -1,7 +1,10 @@
|
||||
//@ known-bug: #139462
|
||||
// This is a regression test for <https://github.com/rust-lang/rust/issues/139462>.
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Cdebuginfo=2
|
||||
//@ ignore-backends: gcc
|
||||
#![feature(unsafe_binders)]
|
||||
//~^ WARN the feature `unsafe_binders` is incomplete
|
||||
|
||||
use std::unsafe_binder::wrap_binder;
|
||||
fn main() {
|
||||
let foo = 0;
|
||||
@@ -0,0 +1,11 @@
|
||||
warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/unsafe-binders-debuginfo.rs:5:12
|
||||
|
|
||||
LL | #![feature(unsafe_binders)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Reference in New Issue
Block a user