ir: Add support for Self on struct and union fields.

This commit is contained in:
Emilio Cobos Álvarez
2020-01-16 15:56:52 +01:00
parent 44d7cb4214
commit ff8e5d591d
18 changed files with 316 additions and 8 deletions
+16 -6
View File
@@ -65,6 +65,8 @@ impl Struct {
}
};
let path = Path::new(item.ident.to_string());
// Ensure we can safely represent the struct given the configuration.
if let Some(align) = repr.align {
layout_config.ensure_safe_to_represent(&align)?;
@@ -76,14 +78,15 @@ impl Struct {
let out = fields
.named
.iter()
.try_skip_map(|x| x.as_ident_and_type())?;
.try_skip_map(|x| x.as_ident_and_type(&path))?;
(out, false)
}
syn::Fields::Unnamed(ref fields) => {
let mut out = Vec::new();
let mut current = 0;
for field in fields.unnamed.iter() {
if let Some(x) = Type::load(&field.ty)? {
if let Some(mut x) = Type::load(&field.ty)? {
x.replace_self_with(&path);
out.push((format!("{}", current), x, Documentation::load(&field.attrs)));
current += 1;
}
@@ -96,7 +99,7 @@ impl Struct {
let is_enum_variant_body = false;
Ok(Struct::new(
Path::new(item.ident.to_string()),
path,
GenericParams::new(&item.generics),
fields,
is_tagged,
@@ -639,11 +642,17 @@ impl Source for Struct {
}
pub trait SynFieldHelpers {
fn as_ident_and_type(&self) -> Result<Option<(String, Type, Documentation)>, String>;
fn as_ident_and_type(
&self,
self_path: &Path,
) -> Result<Option<(String, Type, Documentation)>, String>;
}
impl SynFieldHelpers for syn::Field {
fn as_ident_and_type(&self) -> Result<Option<(String, Type, Documentation)>, String> {
fn as_ident_and_type(
&self,
self_path: &Path,
) -> Result<Option<(String, Type, Documentation)>, String> {
let ident = self
.ident
.as_ref()
@@ -651,7 +660,8 @@ impl SynFieldHelpers for syn::Field {
.clone();
let converted_ty = Type::load(&self.ty)?;
if let Some(x) = converted_ty {
if let Some(mut x) = converted_ty {
x.replace_self_with(self_path);
Ok(Some((
ident.to_string(),
x,
+4 -2
View File
@@ -50,17 +50,19 @@ impl Union {
layout_config.ensure_safe_to_represent(&align)?;
}
let path = Path::new(item.ident.to_string());
let (fields, tuple_union) = {
let out = item
.fields
.named
.iter()
.try_skip_map(|x| x.as_ident_and_type())?;
.try_skip_map(|x| x.as_ident_and_type(&path))?;
(out, false)
};
Ok(Union::new(
Path::new(item.ident.to_string()),
path,
GenericParams::new(&item.generics),
fields,
repr.align,
+15
View File
@@ -0,0 +1,15 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Foo_Bar {
const int32_t *something;
} Foo_Bar;
typedef struct Bar {
int32_t something;
Foo_Bar subexpressions;
} Bar;
void root(Bar b);
@@ -0,0 +1,23 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Foo_Bar {
const int32_t *something;
} Foo_Bar;
typedef struct Bar {
int32_t something;
Foo_Bar subexpressions;
} Bar;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(Bar b);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+15
View File
@@ -0,0 +1,15 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Foo_Bar {
const int32_t *something;
} Foo_Bar;
typedef union Bar {
int32_t something;
Foo_Bar subexpressions;
} Bar;
void root(Bar b);
@@ -0,0 +1,23 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Foo_Bar {
const int32_t *something;
} Foo_Bar;
typedef union Bar {
int32_t something;
Foo_Bar subexpressions;
} Bar;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(Bar b);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+15
View File
@@ -0,0 +1,15 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
const int32_t *something;
} Foo_Bar;
typedef struct {
int32_t something;
Foo_Bar subexpressions;
} Bar;
void root(Bar b);
+23
View File
@@ -0,0 +1,23 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
const int32_t *something;
} Foo_Bar;
typedef struct {
int32_t something;
Foo_Bar subexpressions;
} Bar;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(Bar b);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+20
View File
@@ -0,0 +1,20 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <new>
template<typename T>
struct Foo {
const int32_t *something;
};
struct Bar {
int32_t something;
Foo<Bar> subexpressions;
};
extern "C" {
void root(Bar b);
} // extern "C"
+15
View File
@@ -0,0 +1,15 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Foo_Bar {
const int32_t *something;
};
struct Bar {
int32_t something;
struct Foo_Bar subexpressions;
};
void root(struct Bar b);
@@ -0,0 +1,23 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Foo_Bar {
const int32_t *something;
};
struct Bar {
int32_t something;
struct Foo_Bar subexpressions;
};
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(struct Bar b);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+15
View File
@@ -0,0 +1,15 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Foo_Bar {
const int32_t *something;
};
union Bar {
int32_t something;
struct Foo_Bar subexpressions;
};
void root(union Bar b);
@@ -0,0 +1,23 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Foo_Bar {
const int32_t *something;
};
union Bar {
int32_t something;
struct Foo_Bar subexpressions;
};
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(union Bar b);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+15
View File
@@ -0,0 +1,15 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
const int32_t *something;
} Foo_Bar;
typedef union {
int32_t something;
Foo_Bar subexpressions;
} Bar;
void root(Bar b);
+23
View File
@@ -0,0 +1,23 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
const int32_t *something;
} Foo_Bar;
typedef union {
int32_t something;
Foo_Bar subexpressions;
} Bar;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(Bar b);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+20
View File
@@ -0,0 +1,20 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <new>
template<typename T>
struct Foo {
const int32_t *something;
};
union Bar {
int32_t something;
Foo<Bar> subexpressions;
};
extern "C" {
void root(Bar b);
} // extern "C"
+14
View File
@@ -0,0 +1,14 @@
#[repr(C)]
pub struct Foo<T> {
something: *const i32,
phantom: std::marker::PhantomData<T>,
}
#[repr(C)]
pub struct Bar {
something: i32,
subexpressions: Foo<Self>,
}
#[no_mangle]
pub extern "C" fn root(b: Bar) {}
+14
View File
@@ -0,0 +1,14 @@
#[repr(C)]
pub struct Foo<T> {
something: *const i32,
phantom: std::marker::PhantomData<T>,
}
#[repr(C)]
pub union Bar {
something: i32,
subexpressions: Foo<Self>,
}
#[no_mangle]
pub extern "C" fn root(b: Bar) {}