Support structs in type info reflection
This commit is contained in:
parent
18d13b5332
commit
b23d308853
8 changed files with 333 additions and 39 deletions
|
|
@ -1,18 +1,36 @@
|
|||
use rustc_abi::FieldIdx;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Const, ScalarInt, Ty};
|
||||
use rustc_middle::ty::{self, AdtDef, AdtKind, Const, GenericArgs, ScalarInt, Ty, VariantDef};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::const_eval::CompileTimeMachine;
|
||||
use crate::interpret::{
|
||||
CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable,
|
||||
interp_ok,
|
||||
CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Projectable, Scalar,
|
||||
Writeable, interp_ok,
|
||||
};
|
||||
|
||||
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||
/// Equivalent to `project_downcast`, but identifies the variant by name instead of index.
|
||||
fn downcast<'a>(
|
||||
&self,
|
||||
place: &(impl Writeable<'tcx, CtfeProvenance> + 'a),
|
||||
name: Symbol,
|
||||
) -> InterpResult<'tcx, (VariantIdx, impl Writeable<'tcx, CtfeProvenance> + 'a)> {
|
||||
let variants = place.layout().ty.ty_adt_def().unwrap().variants();
|
||||
let variant_idx = variants
|
||||
.iter_enumerated()
|
||||
.find(|(_idx, var)| var.name == name)
|
||||
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
|
||||
.0;
|
||||
|
||||
interp_ok((variant_idx, self.project_downcast(place, variant_idx)?))
|
||||
}
|
||||
|
||||
/// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place.
|
||||
pub(crate) fn write_type_info(
|
||||
&mut self,
|
||||
|
|
@ -26,22 +44,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
// Fill all fields of the `TypeInfo` struct.
|
||||
for (idx, field) in ty_struct.fields.iter_enumerated() {
|
||||
let field_dest = self.project_field(dest, idx)?;
|
||||
let downcast = |name: Symbol| {
|
||||
let variants = field_dest.layout().ty.ty_adt_def().unwrap().variants();
|
||||
let variant_id = variants
|
||||
.iter_enumerated()
|
||||
.find(|(_idx, var)| var.name == name)
|
||||
.unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}"))
|
||||
.0;
|
||||
|
||||
interp_ok((variant_id, self.project_downcast(&field_dest, variant_id)?))
|
||||
};
|
||||
let ptr_bit_width = || self.tcx.data_layout.pointer_size().bits();
|
||||
match field.name {
|
||||
sym::kind => {
|
||||
let variant_index = match ty.kind() {
|
||||
ty::Tuple(fields) => {
|
||||
let (variant, variant_place) = downcast(sym::Tuple)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Tuple)?;
|
||||
// project to the single tuple variant field of `type_info::Tuple` struct type
|
||||
let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
assert_eq!(
|
||||
|
|
@ -59,7 +68,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
variant
|
||||
}
|
||||
ty::Array(ty, len) => {
|
||||
let (variant, variant_place) = downcast(sym::Array)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Array)?;
|
||||
let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
|
||||
self.write_array_type_info(array_place, *ty, *len)?;
|
||||
|
|
@ -67,23 +77,38 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
variant
|
||||
}
|
||||
ty::Slice(ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Slice)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Slice)?;
|
||||
let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
|
||||
self.write_slice_type_info(slice_place, *ty)?;
|
||||
|
||||
variant
|
||||
}
|
||||
ty::Adt(adt_def, generics) => {
|
||||
// TODO(type_info): Handle enum and union
|
||||
if !adt_def.is_struct() {
|
||||
self.downcast(&field_dest, sym::Other)?.0
|
||||
} else {
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Struct)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_adt_type_info(place, (ty, *adt_def), generics)?;
|
||||
variant
|
||||
}
|
||||
}
|
||||
ty::Bool => {
|
||||
let (variant, _variant_place) = downcast(sym::Bool)?;
|
||||
let (variant, _variant_place) =
|
||||
self.downcast(&field_dest, sym::Bool)?;
|
||||
variant
|
||||
}
|
||||
ty::Char => {
|
||||
let (variant, _variant_place) = downcast(sym::Char)?;
|
||||
let (variant, _variant_place) =
|
||||
self.downcast(&field_dest, sym::Char)?;
|
||||
variant
|
||||
}
|
||||
ty::Int(int_ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Int)?;
|
||||
let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_int_type_info(
|
||||
place,
|
||||
|
|
@ -93,7 +118,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
variant
|
||||
}
|
||||
ty::Uint(uint_ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Int)?;
|
||||
let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_int_type_info(
|
||||
place,
|
||||
|
|
@ -103,17 +128,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
variant
|
||||
}
|
||||
ty::Float(float_ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Float)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Float)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_float_type_info(place, float_ty.bit_width())?;
|
||||
variant
|
||||
}
|
||||
ty::Str => {
|
||||
let (variant, _variant_place) = downcast(sym::Str)?;
|
||||
let (variant, _variant_place) = self.downcast(&field_dest, sym::Str)?;
|
||||
variant
|
||||
}
|
||||
ty::Ref(_, ty, mutability) => {
|
||||
let (variant, variant_place) = downcast(sym::Reference)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Reference)?;
|
||||
let reference_place =
|
||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_reference_type_info(reference_place, *ty, *mutability)?;
|
||||
|
|
@ -121,7 +148,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
variant
|
||||
}
|
||||
ty::RawPtr(ty, mutability) => {
|
||||
let (variant, variant_place) = downcast(sym::Pointer)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::Pointer)?;
|
||||
let pointer_place =
|
||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
|
||||
|
|
@ -130,13 +158,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
variant
|
||||
}
|
||||
ty::Dynamic(predicates, region) => {
|
||||
let (variant, variant_place) = downcast(sym::DynTrait)?;
|
||||
let (variant, variant_place) =
|
||||
self.downcast(&field_dest, sym::DynTrait)?;
|
||||
let dyn_place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_dyn_trait_type_info(dyn_place, *predicates, *region)?;
|
||||
variant
|
||||
}
|
||||
ty::Adt(_, _)
|
||||
| ty::Foreign(_)
|
||||
ty::Foreign(_)
|
||||
| ty::Pat(_, _)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
|
|
@ -151,14 +179,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
| ty::Bound(..)
|
||||
| ty::Placeholder(_)
|
||||
| ty::Infer(..)
|
||||
| ty::Error(_) => downcast(sym::Other)?.0,
|
||||
| ty::Error(_) => self.downcast(&field_dest, sym::Other)?.0,
|
||||
};
|
||||
self.write_discriminant(variant_index, &field_dest)?
|
||||
}
|
||||
sym::size => {
|
||||
let layout = self.layout_of(ty)?;
|
||||
let variant_index = if layout.is_sized() {
|
||||
let (variant, variant_place) = downcast(sym::Some)?;
|
||||
let (variant, variant_place) = self.downcast(&field_dest, sym::Some)?;
|
||||
let size_field_place =
|
||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_scalar(
|
||||
|
|
@ -168,7 +196,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
)?;
|
||||
variant
|
||||
} else {
|
||||
downcast(sym::None)?.0
|
||||
self.downcast(&field_dest, sym::None)?.0
|
||||
};
|
||||
self.write_discriminant(variant_index, &field_dest)?;
|
||||
}
|
||||
|
|
@ -204,7 +232,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
|
||||
while let Some((i, place)) = fields_places.next(self)? {
|
||||
let field_ty = fields[i as usize];
|
||||
self.write_field(field_ty, place, tuple_layout, i)?;
|
||||
self.write_field(field_ty, place, tuple_layout, None, i)?;
|
||||
}
|
||||
|
||||
let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable);
|
||||
|
|
@ -219,6 +247,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
field_ty: Ty<'tcx>,
|
||||
place: MPlaceTy<'tcx>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
name: Option<Symbol>,
|
||||
idx: u64,
|
||||
) -> InterpResult<'tcx> {
|
||||
for (field_idx, field_ty_field) in
|
||||
|
|
@ -226,6 +255,15 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
{
|
||||
let field_place = self.project_field(&place, field_idx)?;
|
||||
match field_ty_field.name {
|
||||
sym::name => {
|
||||
let name = match name.as_ref() {
|
||||
Some(name) => Cow::Borrowed(name.as_str()),
|
||||
None => Cow::Owned(idx.to_string()), // For tuples
|
||||
};
|
||||
let name_place = self.allocate_str_dedup(&name)?;
|
||||
let ptr = self.mplace_to_ref(&name_place)?;
|
||||
self.write_immediate(*ptr, &field_place)?
|
||||
}
|
||||
sym::ty => self.write_type_id(field_ty, &field_place)?,
|
||||
sym::offset => {
|
||||
let offset = layout.fields.offset(idx as usize);
|
||||
|
|
@ -287,6 +325,81 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
interp_ok(())
|
||||
}
|
||||
|
||||
// FIXME(type_info): No semver considerations for now
|
||||
pub(crate) fn write_adt_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
adt: (Ty<'tcx>, AdtDef<'tcx>),
|
||||
generics: &'tcx GenericArgs<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let (adt_ty, adt_def) = adt;
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Struct => self.write_struct_type_info(
|
||||
place,
|
||||
(adt_ty, adt_def.variant(VariantIdx::ZERO)),
|
||||
generics,
|
||||
),
|
||||
AdtKind::Union => todo!(),
|
||||
AdtKind::Enum => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_struct_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
struct_: (Ty<'tcx>, &'tcx VariantDef),
|
||||
generics: &'tcx GenericArgs<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let (struct_ty, struct_def) = struct_;
|
||||
let struct_layout = self.layout_of(struct_ty)?;
|
||||
|
||||
for (field_idx, field) in
|
||||
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||
{
|
||||
let field_place = self.project_field(&place, field_idx)?;
|
||||
|
||||
match field.name {
|
||||
sym::fields => {
|
||||
let fields_slice_place = field_place;
|
||||
let field_type = fields_slice_place
|
||||
.layout()
|
||||
.ty
|
||||
.builtin_deref(false)
|
||||
.unwrap()
|
||||
.sequence_element_type(self.tcx.tcx);
|
||||
let fields_layout = self.layout_of(Ty::new_array(
|
||||
self.tcx.tcx,
|
||||
field_type,
|
||||
struct_def.fields.len() as u64,
|
||||
))?;
|
||||
let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?;
|
||||
let mut fields_places = self.project_array_fields(&fields_place)?;
|
||||
|
||||
for field_def in &struct_def.fields {
|
||||
let (i, place) = fields_places.next(self)?.unwrap();
|
||||
let field_ty = field_def.ty(*self.tcx, generics);
|
||||
self.write_field(field_ty, place, struct_layout, Some(field_def.name), i)?;
|
||||
}
|
||||
|
||||
let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable);
|
||||
let ptr = Immediate::new_slice(
|
||||
fields_place.ptr(),
|
||||
struct_def.fields.len() as u64,
|
||||
self,
|
||||
);
|
||||
self.write_immediate(ptr, &fields_slice_place)?
|
||||
}
|
||||
sym::non_exhaustive => {
|
||||
let is_non_exhaustive = struct_def.is_field_list_non_exhaustive();
|
||||
self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)?
|
||||
}
|
||||
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||
}
|
||||
}
|
||||
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn write_int_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
|
|
|
|||
|
|
@ -372,6 +372,7 @@ symbols! {
|
|||
Stdin,
|
||||
Str,
|
||||
String,
|
||||
Struct,
|
||||
StructuralPartialEq,
|
||||
SubdiagMessage,
|
||||
Subdiagnostic,
|
||||
|
|
@ -1086,6 +1087,7 @@ symbols! {
|
|||
ffi_returns_twice,
|
||||
field,
|
||||
field_init_shorthand,
|
||||
fields,
|
||||
file,
|
||||
file_options,
|
||||
flags,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ pub enum TypeKind {
|
|||
Slice(Slice),
|
||||
/// Dynamic Traits.
|
||||
DynTrait(DynTrait),
|
||||
/// Structs.
|
||||
Struct(Struct),
|
||||
/// Primitive boolean type.
|
||||
Bool(Bool),
|
||||
/// Primitive character type.
|
||||
|
|
@ -81,6 +83,8 @@ pub struct Tuple {
|
|||
#[non_exhaustive]
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
pub struct Field {
|
||||
/// The name of the field.
|
||||
pub name: &'static str,
|
||||
/// The field's type.
|
||||
pub ty: TypeId,
|
||||
/// Offset in bytes from the parent type
|
||||
|
|
@ -137,6 +141,17 @@ pub struct Trait {
|
|||
pub is_auto: bool,
|
||||
}
|
||||
|
||||
/// Compile-time type information about arrays.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
#[unstable(feature = "type_info", issue = "146922")]
|
||||
pub struct Struct {
|
||||
/// All fields of the struct.
|
||||
pub fields: &'static [Field],
|
||||
/// Whether the struct field list is non-exhaustive.
|
||||
pub non_exhaustive: bool,
|
||||
}
|
||||
|
||||
/// Compile-time type information about `bool`.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::any::{Any, TypeId};
|
||||
use std::mem::offset_of;
|
||||
use std::mem::type_info::{Type, TypeKind};
|
||||
|
||||
#[test]
|
||||
|
|
@ -66,6 +69,54 @@ fn test_tuples() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_structs() {
|
||||
use TypeKind::*;
|
||||
|
||||
const {
|
||||
struct TestStruct {
|
||||
first: u8,
|
||||
second: u16,
|
||||
reference: &'static u16,
|
||||
}
|
||||
|
||||
let Type { kind: Struct(ty), size, .. } = Type::of::<TestStruct>() else { panic!() };
|
||||
assert!(size == Some(size_of::<TestStruct>()));
|
||||
assert!(!ty.non_exhaustive);
|
||||
assert!(ty.fields.len() == 3);
|
||||
assert!(ty.fields[0].name == "first");
|
||||
assert!(ty.fields[0].ty == TypeId::of::<u8>());
|
||||
assert!(ty.fields[0].offset == offset_of!(TestStruct, first));
|
||||
assert!(ty.fields[1].name == "second");
|
||||
assert!(ty.fields[1].ty == TypeId::of::<u16>());
|
||||
assert!(ty.fields[1].offset == offset_of!(TestStruct, second));
|
||||
assert!(ty.fields[2].name == "reference");
|
||||
assert!(ty.fields[2].ty != TypeId::of::<&'static u16>()); // FIXME(type_info): should be ==
|
||||
assert!(ty.fields[2].offset == offset_of!(TestStruct, reference));
|
||||
}
|
||||
|
||||
const {
|
||||
#[non_exhaustive]
|
||||
struct NonExhaustive {
|
||||
a: u8,
|
||||
}
|
||||
|
||||
let Type { kind: Struct(ty), .. } = Type::of::<NonExhaustive>() else { panic!() };
|
||||
assert!(ty.non_exhaustive);
|
||||
}
|
||||
|
||||
const {
|
||||
struct TupleStruct(u8, u16);
|
||||
|
||||
let Type { kind: Struct(ty), .. } = Type::of::<TupleStruct>() else { panic!() };
|
||||
assert!(ty.fields.len() == 2);
|
||||
assert!(ty.fields[0].name == "0");
|
||||
assert!(ty.fields[0].ty == TypeId::of::<u8>());
|
||||
assert!(ty.fields[1].name == "1");
|
||||
assert!(ty.fields[1].ty == TypeId::of::<u16>());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitives() {
|
||||
use TypeKind::*;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
error[E0599]: the method `clone` exists for struct `Struct<A>`, but its trait bounds were not satisfied
|
||||
error[E0599]: the method `clone` exists for struct `issue_69725::Struct<A>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-69725.rs:9:32
|
||||
|
|
||||
LL | let _ = Struct::<A>::new().clone();
|
||||
| ^^^^^ method cannot be called on `Struct<A>` due to unsatisfied trait bounds
|
||||
| ^^^^^ method cannot be called on `issue_69725::Struct<A>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $DIR/auxiliary/issue-69725.rs:2:1
|
||||
|
|
||||
LL | pub struct Struct<A>(A);
|
||||
| -------------------- doesn't satisfy `Struct<A>: Clone`
|
||||
| -------------------- doesn't satisfy `issue_69725::Struct<A>: Clone`
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`A: Clone`
|
||||
which is required by `Struct<A>: Clone`
|
||||
which is required by `issue_69725::Struct<A>: Clone`
|
||||
help: consider restricting the type parameter to satisfy the trait bound
|
||||
|
|
||||
LL | fn crash<A>() where A: Clone {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ Type {
|
|||
Tuple {
|
||||
fields: [
|
||||
Field {
|
||||
name: "0",
|
||||
ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
|
||||
offset: 0,
|
||||
},
|
||||
Field {
|
||||
name: "1",
|
||||
ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
|
||||
offset: 1,
|
||||
},
|
||||
Field {
|
||||
name: "2",
|
||||
ty: TypeId(0x41223169ff28813ba79b7268a2a968d9),
|
||||
offset: 2,
|
||||
},
|
||||
|
|
@ -143,7 +146,18 @@ Type {
|
|||
),
|
||||
}
|
||||
Type {
|
||||
kind: Other,
|
||||
kind: Struct(
|
||||
Struct {
|
||||
fields: [
|
||||
Field {
|
||||
name: "a",
|
||||
ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7),
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
non_exhaustive: false,
|
||||
},
|
||||
),
|
||||
size: Some(
|
||||
4,
|
||||
),
|
||||
|
|
@ -154,6 +168,45 @@ Type {
|
|||
12,
|
||||
),
|
||||
}
|
||||
Type {
|
||||
kind: Struct(
|
||||
Struct {
|
||||
fields: [
|
||||
Field {
|
||||
name: "a",
|
||||
ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7),
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
non_exhaustive: true,
|
||||
},
|
||||
),
|
||||
size: Some(
|
||||
4,
|
||||
),
|
||||
}
|
||||
Type {
|
||||
kind: Struct(
|
||||
Struct {
|
||||
fields: [
|
||||
Field {
|
||||
name: "0",
|
||||
ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7),
|
||||
offset: 8,
|
||||
},
|
||||
Field {
|
||||
name: "1",
|
||||
ty: TypeId(0x9ed91be891e304132cb86891e578f4a5),
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
non_exhaustive: false,
|
||||
},
|
||||
),
|
||||
size: Some(
|
||||
12,
|
||||
),
|
||||
}
|
||||
Type {
|
||||
kind: Reference(
|
||||
Reference {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ Type {
|
|||
Tuple {
|
||||
fields: [
|
||||
Field {
|
||||
name: "0",
|
||||
ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
|
||||
offset: 0,
|
||||
},
|
||||
Field {
|
||||
name: "1",
|
||||
ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb),
|
||||
offset: 1,
|
||||
},
|
||||
Field {
|
||||
name: "2",
|
||||
ty: TypeId(0x41223169ff28813ba79b7268a2a968d9),
|
||||
offset: 2,
|
||||
},
|
||||
|
|
@ -143,7 +146,18 @@ Type {
|
|||
),
|
||||
}
|
||||
Type {
|
||||
kind: Other,
|
||||
kind: Struct(
|
||||
Struct {
|
||||
fields: [
|
||||
Field {
|
||||
name: "a",
|
||||
ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7),
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
non_exhaustive: false,
|
||||
},
|
||||
),
|
||||
size: Some(
|
||||
4,
|
||||
),
|
||||
|
|
@ -154,6 +168,45 @@ Type {
|
|||
24,
|
||||
),
|
||||
}
|
||||
Type {
|
||||
kind: Struct(
|
||||
Struct {
|
||||
fields: [
|
||||
Field {
|
||||
name: "a",
|
||||
ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7),
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
non_exhaustive: true,
|
||||
},
|
||||
),
|
||||
size: Some(
|
||||
4,
|
||||
),
|
||||
}
|
||||
Type {
|
||||
kind: Struct(
|
||||
Struct {
|
||||
fields: [
|
||||
Field {
|
||||
name: "0",
|
||||
ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7),
|
||||
offset: 8,
|
||||
},
|
||||
Field {
|
||||
name: "1",
|
||||
ty: TypeId(0x9ed91be891e304132cb86891e578f4a5),
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
non_exhaustive: false,
|
||||
},
|
||||
),
|
||||
size: Some(
|
||||
16,
|
||||
),
|
||||
}
|
||||
Type {
|
||||
kind: Reference(
|
||||
Reference {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@ struct Foo {
|
|||
a: u32,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
struct NonExhaustiveStruct {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
struct TupleStruct(u32, u64);
|
||||
|
||||
enum Bar {
|
||||
Some(u32),
|
||||
None,
|
||||
|
|
@ -37,7 +44,7 @@ fn main() {
|
|||
[u8; 2],
|
||||
i8, i32, i64, i128, isize,
|
||||
u8, u32, u64, u128, usize,
|
||||
Foo, Bar,
|
||||
Foo, Bar, NonExhaustiveStruct, TupleStruct,
|
||||
&Unsized, &str, &[u8],
|
||||
str, [u8],
|
||||
&u8, &mut u8,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue