Skip to content

Commit 8b9d35e

Browse files
committed
[derive] Fix the 'simple' integeration tests
We now manage to auto-derive 'StaticReflect' appropriately. Also, the 'field_offset!' macro has been updated to not involve undefined behavior :D
1 parent d31dde2 commit 8b9d35e

File tree

9 files changed

+131
-78
lines changed

9 files changed

+131
-78
lines changed

lib/derive-internals/Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,3 @@ indexmap = "1.6"
1313
[dependencies.syn]
1414
version = "1"
1515
features = ["full", "extra-traits"]
16-
17-
[dev-dependencies]
18-
# Testing
19-
static-reflect = { version = "0.1.0", path = "../.." }

lib/derive-internals/src/fields.rs

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -93,62 +93,61 @@ impl Parse for DeriveFieldOptions {
9393
}
9494
}
9595

96-
pub fn derive_static_reflect(input: &DeriveInput) -> TokenStream {
96+
pub fn derive_static_reflect(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
9797
let name = &input.ident;
9898
if !has_repr_c(&input) {
99-
return syn::Error::new(
100-
Span::call_site(),
99+
return Err(syn::Error::new(
100+
name.span(),
101101
"StaticReflect requires repr(C)"
102-
).to_compile_error().into()
102+
))
103103
}
104104

105105
let generics = add_type_bounds(&input.generics, &[parse_quote!(::reflect::StaticReflect)]);
106106
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
107107

108-
let mut verify_fields = Vec::new();
109108
let mut extra_defs = Vec::new();
110109
let static_type = match input.data {
111110
Data::Struct(ref data) => {
112111
handle_type(
113112
StructHandler::new(data, name),
114-
&mut verify_fields, &name,
113+
&name,
115114
quote!(#impl_generics),
116115
quote!(#ty_generics),
117116
quote!(#where_clause),
118117
&mut extra_defs
119-
)
118+
)?
120119
},
121-
Data::Enum(ref data) => enum_static_type(data, &name),
120+
Data::Enum(ref data) => enum_static_type(data, &name)?,
122121
Data::Union(ref data) => {
123122
handle_type(
124123
UnionTypeHandler { data, name },
125-
&mut verify_fields, &name,
124+
&name,
126125
quote!(#impl_generics),
127126
quote!(#ty_generics),
128127
quote!(#where_clause),
129128
&mut extra_defs
130-
)
129+
)?
131130
},
132-
}.unwrap_or_else(|e| e.to_compile_error());
131+
};
133132

134133
let r = quote! {
135134
#(#extra_defs)*
136-
impl #impl_generics static_reflect::StaticReflect for #name #ty_generics #where_clause {
137-
const TYPE_INFO: static_reflect::types::TypeInfo<'static> = #static_type;
138-
}
139-
// NOTE: We've verified all our fields implement `NativeRepr`
140-
unsafe impl #impl_generics static_reflect::NativeRepr for #name #ty_generics #where_clause {
141-
const _VERIFY_TRANSPARENT_REPR: u32 = {
142-
// Verify all our fields implement `NativeRepr`
143-
0 #(+ #verify_fields)*
135+
unsafe impl #impl_generics static_reflect::StaticReflect for #name #ty_generics #where_clause {
136+
const TYPE_INFO: static_reflect::types::TypeInfo<'static> = {
137+
/*
138+
* NOTE: All our fields are assumed to implement `StaticReflect`,
139+
* because there is no other way they could show up
140+
* in the generated `TypeInfo`.
141+
*/
142+
#static_type
144143
};
145144
}
146145
};
147146
crate::utils::debug_derive("StaticReflect", &input.ident, &r);
148-
r.into()
147+
Ok(r)
149148
}
150149
fn handle_type<'a, T: TypeHandler<'a>>(
151-
mut target: T, verify_fields: &mut Vec<TokenStream>,
150+
mut target: T,
152151
name: &Ident,
153152
impl_generics: TokenStream,
154153
ty_generics: TokenStream,
@@ -165,8 +164,6 @@ fn handle_type<'a, T: TypeHandler<'a>>(
165164
field_associated_types.push(quote!(type #field_name = #field_type;));
166165
let field_def_type = T::field_def_type(Some(quote!(#field_type)));
167166
field_defs.push(quote!(pub #field_name: #field_def_type,));
168-
// NOTE: Must use size_of<#original_type> (See above)
169-
verify_fields.push(field.verify_type());
170167
})?;
171168
let field_info_struct_name = Ident::new(
172169
&format!("_FieldInfo{}", name),
@@ -197,7 +194,7 @@ fn handle_type<'a, T: TypeHandler<'a>>(
197194
.map(|(name, def)| quote!(#name: #def,))
198195
.collect::<Vec<TokenStream>>();
199196
extra_defs.push(quote!(
200-
impl #impl_generics static_reflect::FieldReflect for #name #ty_generics #where_clause {
197+
unsafe impl #impl_generics static_reflect::FieldReflect for #name #ty_generics #where_clause {
201198
type NamedFieldInfo = #field_info_struct_name;
202199
const NAMED_FIELD_INFO: Self::NamedFieldInfo = #field_info_struct_name {
203200
#(#field_inits)*
@@ -208,11 +205,11 @@ fn handle_type<'a, T: TypeHandler<'a>>(
208205
let field_def_type_name = T::field_def_type(None);
209206
let type_def_type = T::type_def_type();
210207
let header = quote! {
211-
use static_reflect::{AsmRepr, AsmFieldInfo};
212-
use static_reflect::types::AsmType;
208+
use static_reflect::{StaticReflect, FieldReflect};
209+
use static_reflect::types::TypeInfo;
213210
use #field_def_type_name;
214211
use #type_def_type;
215-
const _FIELDS: &'static [#field_def_type_name<'static>] = &[#(<#name as AsmFieldInfo>::FIELD_INFO.#field_names.erase()),*];
212+
const _FIELDS: &'static [#field_def_type_name<'static>] = &[#(<#name as FieldReflect>::NAMED_FIELD_INFO.#field_names.erase()),*];
216213
};
217214
let static_def = target.create_static_def(header);
218215
let into_type = T::def_into_type(quote!(_DEF));
@@ -246,12 +243,6 @@ struct FieldInfo<'a> {
246243
static_type: Type,
247244
static_def: TokenStream
248245
}
249-
impl<'a> FieldInfo<'a> {
250-
fn verify_type(&self) -> TokenStream {
251-
let field_type = &self.static_type;
252-
quote!(<#field_type as ::static_reflect::StaticReflect>::_VERIFY_TRANSPARENT_REPR)
253-
}
254-
}
255246
struct StructHandler<'a> {
256247
name: &'a Ident,
257248
data: &'a DataStruct,
@@ -399,7 +390,7 @@ impl<'a> TypeHandler<'a> for UnionTypeHandler<'a> {
399390
}
400391

401392
fn def_into_type(def_ref: TokenStream) -> TokenStream {
402-
quote!(static_reflect::types::AsmType::Union(#def_ref))
393+
quote!(static_reflect::types::TypeInfo::Union(#def_ref))
403394
}
404395

405396
fn handle_fields<F: FnMut(FieldInfo<'a>)>(&mut self, mut handler: F) -> syn::Result<()> {

lib/derive/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@ proc-macro = true
1010

1111
[dependencies]
1212
proc-macro2 = "^1"
13+
syn = "1"
1314

1415
# Actual implementation
1516
[dependencies.static-reflect-derive-internals]
1617
version = "0.1.0"
1718
path = "../derive-internals"
19+
20+
[dev-dependencies]
21+
# Testing
22+
static-reflect = { version = "0.1.0", path = "../.." }

lib/derive/src/lib.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,25 @@
1-
extern proc_macro;
1+
extern crate proc_macro;
2+
extern crate static_reflect_derive_internals as internals;
3+
4+
use syn::{parse_macro_input, Item, DeriveInput};
5+
6+
#[proc_macro_derive(StaticReflect, attributes(reflect, static_reflect))]
7+
pub fn derive_static_reflect(raw_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
8+
let input: DeriveInput = parse_macro_input!(raw_input as DeriveInput);
9+
match internals::fields::derive_static_reflect(&input) {
10+
Ok(tokens) => tokens.into(),
11+
Err(e) => e.into_compile_error().into()
12+
}
13+
}
14+
15+
16+
#[proc_macro_attribute]
17+
pub fn reflect_func(args: proc_macro::TokenStream, input: proc_macro::TokenStream) -> proc_macro::TokenStream {
18+
let _original_input = input.clone();
19+
let input: Item = parse_macro_input!(input as Item);
20+
let args = parse_macro_input!(args as internals::func::FuncArgs);
21+
match internals::derive_reflect_func(args, &input) {
22+
Ok(tokens) => tokens.into(),
23+
Err(e) => e.into_compile_error().into()
24+
}
25+
}

lib/derive-internals/tests/funcs.rs renamed to lib/derive/tests/funcs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::os::raw::c_void;
33

44
use duckasm_derive::duckasm_func;
5-
use duckasm_repr::AsmRepr;
5+
use static_repr::AsmRepr;
66
use duckasm_repr::funcs::{FunctionDeclaration, FunctionLocation, SignatureDef};
77
use duckasm_repr::types::AsmType;
88
use std::marker::PhantomData;

lib/derive-internals/tests/simple.rs renamed to lib/derive/tests/simple.rs

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
// const_fn is used by AsmType
44
const_fn, const_panic
55
)]
6-
use duckasm_repr::field_offset;
7-
use duckasm_repr::{AsmRepr, AsmFieldInfo};
8-
use duckasm_repr::types::{AsmType, FieldDef, StructureDef, UnionDef, UnionFieldDef, TypeId};
6+
7+
use static_reflect::{field_offset, StaticReflect, FieldReflect};
8+
use static_reflect::types::{TypeInfo, FieldDef, StructureDef, UnionDef, UnionFieldDef, TypeId};
99
use std::mem::{size_of, align_of};
1010

11-
use duckasm_derive::{AsmRepr};
11+
use static_reflect_derive::{StaticReflect};
1212

13-
#[derive(Copy, Clone, Debug, PartialEq, AsmRepr)]
13+
#[derive(Copy, Clone, Debug, PartialEq, StaticReflect)]
1414
#[repr(C)]
1515
pub struct Nested {
1616
cycle: *mut SimpleStruct,
1717
float: f64,
1818
number: u64,
1919
}
2020

21-
#[derive(AsmRepr)]
21+
#[derive(StaticReflect)]
2222
#[repr(C)]
2323
pub struct SimpleStruct {
2424
// We can have pointers to anything
@@ -38,7 +38,7 @@ fn leak_vec<T>(elements: Vec<T>) -> &'static [T] {
3838
}
3939

4040
#[repr(C)]
41-
#[derive(AsmRepr)]
41+
#[derive(StaticReflect)]
4242
union SimpleUnion {
4343
pub text: *mut String,
4444
b: bool,
@@ -48,34 +48,34 @@ union SimpleUnion {
4848

4949
#[test]
5050
fn test_union_types() {
51-
const EXPECTED_UNION: AsmType<'static> = AsmType::Union(&UnionDef {
51+
const EXPECTED_UNION: TypeInfo<'static> = TypeInfo::Union(&UnionDef {
5252
name: "SimpleUnion",
5353
fields: &[
54-
SimpleUnion::FIELD_INFO.text.erase(),
55-
SimpleUnion::FIELD_INFO.b.erase(),
56-
SimpleUnion::FIELD_INFO.f.erase(),
57-
SimpleUnion::FIELD_INFO.nested.erase(),
54+
SimpleUnion::NAMED_FIELD_INFO.text.erase(),
55+
SimpleUnion::NAMED_FIELD_INFO.b.erase(),
56+
SimpleUnion::NAMED_FIELD_INFO.f.erase(),
57+
SimpleUnion::NAMED_FIELD_INFO.nested.erase(),
5858
],
5959
size: size_of::<SimpleUnion>(),
6060
alignment: align_of::<SimpleUnion>()
6161
});
62-
assert_eq!(EXPECTED_UNION, SimpleUnion::STATIC_TYPE);
63-
assert_eq!(SimpleUnion::FIELD_INFO.text, UnionFieldDef {
62+
assert_eq!(EXPECTED_UNION, SimpleUnion::TYPE_INFO);
63+
assert_eq!(SimpleUnion::NAMED_FIELD_INFO.text, UnionFieldDef {
6464
name: "text",
6565
value_type: TypeId::<*mut String>::get(),
6666
index: 0
6767
});
68-
assert_eq!(SimpleUnion::FIELD_INFO.b, UnionFieldDef {
68+
assert_eq!(SimpleUnion::NAMED_FIELD_INFO.b, UnionFieldDef {
6969
name: "b",
7070
value_type: TypeId::<bool>::get(),
7171
index: 1
7272
});
73-
assert_eq!(SimpleUnion::FIELD_INFO.f, UnionFieldDef {
73+
assert_eq!(SimpleUnion::NAMED_FIELD_INFO.f, UnionFieldDef {
7474
name: "f",
7575
value_type: TypeId::<f32>::get(),
7676
index: 2
7777
});
78-
assert_eq!(SimpleUnion::FIELD_INFO.nested, UnionFieldDef {
78+
assert_eq!(SimpleUnion::NAMED_FIELD_INFO.nested, UnionFieldDef {
7979
name: "nested",
8080
value_type: TypeId::<Nested>::get(),
8181
index: 3
@@ -84,30 +84,30 @@ fn test_union_types() {
8484

8585
#[test]
8686
fn test_struct_types() {
87-
const NESTED_TYPE: AsmType<'static> = AsmType::Structure(&StructureDef {
87+
const NESTED_TYPE: TypeInfo<'static> = TypeInfo::Structure(&StructureDef {
8888
name: "Nested",
8989
fields: &[
90-
Nested::FIELD_INFO.cycle.erase(),
91-
Nested::FIELD_INFO.float.erase(),
92-
Nested::FIELD_INFO.number.erase(),
90+
Nested::NAMED_FIELD_INFO.cycle.erase(),
91+
Nested::NAMED_FIELD_INFO.float.erase(),
92+
Nested::NAMED_FIELD_INFO.number.erase(),
9393
],
9494
size: size_of::<Nested>(),
9595
alignment: align_of::<Nested>()
9696
});
97-
assert_eq!(Nested::STATIC_TYPE, NESTED_TYPE);
98-
assert_eq!(Nested::FIELD_INFO.cycle, FieldDef {
97+
assert_eq!(Nested::TYPE_INFO, NESTED_TYPE);
98+
assert_eq!(Nested::NAMED_FIELD_INFO.cycle, FieldDef {
9999
name: "cycle",
100100
value_type: TypeId::<*mut SimpleStruct>::get(),
101101
offset: field_offset!(Nested, cycle),
102102
index: 0
103103
});
104-
assert_eq!(Nested::FIELD_INFO.float, FieldDef {
104+
assert_eq!(Nested::NAMED_FIELD_INFO.float, FieldDef {
105105
name: "float",
106106
value_type: TypeId::<f64>::get(),
107107
offset: field_offset!(Nested, float),
108108
index: 1
109109
});
110-
assert_eq!(Nested::FIELD_INFO.number, FieldDef {
110+
assert_eq!(Nested::NAMED_FIELD_INFO.number, FieldDef {
111111
name: "number",
112112
value_type: TypeId::<u64>::get(),
113113
offset: field_offset!(Nested, number),
@@ -154,8 +154,8 @@ fn test_struct_types() {
154154
];
155155
let static_fields = leak_vec(fields);
156156
assert_eq!(
157-
SimpleStruct::STATIC_TYPE,
158-
AsmType::Structure(&StructureDef {
157+
SimpleStruct::TYPE_INFO,
158+
TypeInfo::Structure(&StructureDef {
159159
name: "SimpleStruct",
160160
fields: static_fields,
161161
size: size_of::<SimpleStruct>(),
@@ -164,34 +164,34 @@ fn test_struct_types() {
164164
);
165165
}
166166

167-
#[derive(AsmRepr)]
167+
#[derive(StaticReflect)]
168168
#[repr(C)]
169169
struct OpaqueArray {
170-
#[duckasm(assume_repr = "i8")]
170+
#[reflect(assume_repr = "i8")]
171171
first: u8,
172-
#[duckasm(opaque_array)]
172+
#[static_reflect(opaque_array)]
173173
array: [*mut String; 42]
174174
}
175175

176176
#[test]
177177
fn test_options() {
178-
const OPAQUE_ARRAY_TYPE: AsmType<'static> = AsmType::Structure(&StructureDef {
178+
const OPAQUE_ARRAY_TYPE: TypeInfo<'static> = TypeInfo::Structure(&StructureDef {
179179
name: "OpaqueArray",
180180
fields: &[
181-
OpaqueArray::FIELD_INFO.first.erase(),
182-
OpaqueArray::FIELD_INFO.array.erase(),
181+
OpaqueArray::NAMED_FIELD_INFO.first.erase(),
182+
OpaqueArray::NAMED_FIELD_INFO.array.erase(),
183183
],
184184
size: size_of::<OpaqueArray>(),
185185
alignment: align_of::<OpaqueArray>()
186186
});
187-
assert_eq!(OPAQUE_ARRAY_TYPE, OpaqueArray::STATIC_TYPE);
188-
assert_eq!(OpaqueArray::FIELD_INFO.first, FieldDef {
187+
assert_eq!(OPAQUE_ARRAY_TYPE, OpaqueArray::TYPE_INFO);
188+
assert_eq!(OpaqueArray::NAMED_FIELD_INFO.first, FieldDef {
189189
name: "first",
190190
value_type: TypeId::<i8>::get(), // It's actually a 'u8', but we assume_repr
191191
offset: field_offset!(OpaqueArray, first),
192192
index: 0
193193
});
194-
assert_eq!(OpaqueArray::FIELD_INFO.array, FieldDef {
194+
assert_eq!(OpaqueArray::NAMED_FIELD_INFO.array, FieldDef {
195195
name: "array",
196196
value_type: TypeId::<*mut String>::get(),
197197
offset: field_offset!(OpaqueArray, array),

0 commit comments

Comments
 (0)