From c732069b2e8b899149a54c26539b843237b85d74 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Sat, 7 May 2022 16:16:42 -0500 Subject: [PATCH] New type GenericParam represents a generic parameter. --- src/bindgen/ir/enumeration.rs | 21 +--- src/bindgen/ir/generic_path.rs | 117 ++++++++++++++---- src/bindgen/ir/opaque.rs | 2 +- src/bindgen/ir/structure.rs | 22 +--- src/bindgen/ir/ty.rs | 2 +- src/bindgen/ir/typedef.rs | 21 +--- src/bindgen/ir/union.rs | 21 +--- src/bindgen/parser.rs | 9 +- tests/expectations/const_generics.both.c | 17 +++ .../expectations/const_generics.both.compat.c | 25 ++++ tests/expectations/const_generics.c | 17 +++ tests/expectations/const_generics.compat.c | 25 ++++ tests/expectations/const_generics.cpp | 21 ++++ tests/expectations/const_generics.pyx | 19 +++ tests/expectations/const_generics.tag.c | 17 +++ .../expectations/const_generics.tag.compat.c | 25 ++++ tests/expectations/const_generics.tag.pyx | 19 +++ .../const_generics_arrayvec.both.c | 11 ++ .../const_generics_arrayvec.both.compat.c | 19 +++ tests/expectations/const_generics_arrayvec.c | 11 ++ .../const_generics_arrayvec.compat.c | 19 +++ .../expectations/const_generics_arrayvec.cpp | 17 +++ .../expectations/const_generics_arrayvec.pyx | 13 ++ .../const_generics_arrayvec.tag.c | 11 ++ .../const_generics_arrayvec.tag.compat.c | 19 +++ .../const_generics_arrayvec.tag.pyx | 13 ++ tests/rust/const_generics.rs | 15 +++ tests/rust/const_generics_arrayvec.rs | 17 +++ 28 files changed, 462 insertions(+), 103 deletions(-) create mode 100644 tests/expectations/const_generics.both.c create mode 100644 tests/expectations/const_generics.both.compat.c create mode 100644 tests/expectations/const_generics.c create mode 100644 tests/expectations/const_generics.compat.c create mode 100644 tests/expectations/const_generics.cpp create mode 100644 tests/expectations/const_generics.pyx create mode 100644 tests/expectations/const_generics.tag.c create mode 100644 tests/expectations/const_generics.tag.compat.c create mode 100644 tests/expectations/const_generics.tag.pyx create mode 100644 tests/expectations/const_generics_arrayvec.both.c create mode 100644 tests/expectations/const_generics_arrayvec.both.compat.c create mode 100644 tests/expectations/const_generics_arrayvec.c create mode 100644 tests/expectations/const_generics_arrayvec.compat.c create mode 100644 tests/expectations/const_generics_arrayvec.cpp create mode 100644 tests/expectations/const_generics_arrayvec.pyx create mode 100644 tests/expectations/const_generics_arrayvec.tag.c create mode 100644 tests/expectations/const_generics_arrayvec.tag.compat.c create mode 100644 tests/expectations/const_generics_arrayvec.tag.pyx create mode 100644 tests/rust/const_generics.rs create mode 100644 tests/rust/const_generics_arrayvec.rs diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index f770e39da..6409a7913 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -383,7 +383,7 @@ impl Enum { } let path = Path::new(item.ident.unraw().to_string()); - let generic_params = GenericParams::new(&item.generics); + let generic_params = GenericParams::load(&item.generics)?; let mut variants = Vec::new(); let mut has_data = false; @@ -616,24 +616,7 @@ impl Item for Enum { library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path.name() - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path.name(), - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); + let mappings = self.generic_params.call(self.path.name(), generic_values); for variant in &self.variants { if let VariantBody::Body { ref body, .. } = variant.body { diff --git a/src/bindgen/ir/generic_path.rs b/src/bindgen/ir/generic_path.rs index 5174df43d..e9f362097 100644 --- a/src/bindgen/ir/generic_path.rs +++ b/src/bindgen/ir/generic_path.rs @@ -3,30 +3,95 @@ use std::ops::Deref; use syn::ext::IdentExt; +use crate::bindgen::cdecl; use crate::bindgen::config::{Config, Language}; use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver}; use crate::bindgen::ir::{ArrayLength, Path, Type}; use crate::bindgen::utilities::IterHelpers; use crate::bindgen::writer::{Source, SourceWriter}; +#[derive(Debug, Clone)] +pub enum GenericParamType { + Type, + Const(Type), +} + +#[derive(Debug, Clone)] +pub struct GenericParam { + name: Path, + ty: GenericParamType, +} + +impl GenericParam { + pub fn new_type_param(name: &str) -> Self { + GenericParam { + name: Path::new(name), + ty: GenericParamType::Type, + } + } + + pub fn load(param: &syn::GenericParam) -> Result, String> { + match *param { + syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => Ok(Some(GenericParam { + name: Path::new(ident.unraw().to_string()), + ty: GenericParamType::Type, + })), + + syn::GenericParam::Lifetime(_) => Ok(None), + + syn::GenericParam::Const(syn::ConstParam { + ref ident, ref ty, .. + }) => match Type::load(ty)? { + None => { + // A type that evaporates, like PhantomData. + Err(format!("unsupported const generic type: {:?}", ty)) + } + Some(ty) => Ok(Some(GenericParam { + name: Path::new(ident.unraw().to_string()), + ty: GenericParamType::Const(ty), + })), + }, + } + } + + pub fn name(&self) -> &Path { + &self.name + } +} + #[derive(Default, Debug, Clone)] -pub struct GenericParams(pub Vec); +pub struct GenericParams(pub Vec); impl GenericParams { - pub fn new(generics: &syn::Generics) -> Self { - GenericParams( - generics - .params - .iter() - .filter_map(|x| match *x { - syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) - | syn::GenericParam::Const(syn::ConstParam { ref ident, .. }) => { - Some(Path::new(ident.unraw().to_string())) - } - _ => None, - }) - .collect(), - ) + pub fn load(generics: &syn::Generics) -> Result { + let mut params = vec![]; + for param in &generics.params { + if let Some(p) = GenericParam::load(param)? { + params.push(p); + } + } + + Ok(GenericParams(params)) + } + + /// Associate each parameter with an argument. + pub fn call<'out>( + &'out self, + item_name: &str, + arguments: &'out [GenericArgument], + ) -> Vec<(&'out Path, &'out GenericArgument)> { + assert!(self.len() > 0, "{} is not generic", item_name); + assert!( + self.len() == arguments.len(), + "{} has {} params but is being instantiated with {} values", + item_name, + self.len(), + arguments.len(), + ); + self.iter() + .map(|param| param.name()) + .zip(arguments.iter()) + .collect() } fn write_internal( @@ -41,9 +106,19 @@ impl GenericParams { if i != 0 { out.write(", "); } - write!(out, "typename {}", item); - if with_default { - write!(out, " = void"); + match item.ty { + GenericParamType::Type => { + write!(out, "typename {}", item.name); + if with_default { + write!(out, " = void"); + } + } + GenericParamType::Const(ref ty) => { + cdecl::write_field(out, ty, item.name.name(), config); + if with_default { + write!(out, " = 0"); + } + } } } out.write(">"); @@ -57,9 +132,9 @@ impl GenericParams { } impl Deref for GenericParams { - type Target = [Path]; + type Target = [GenericParam]; - fn deref(&self) -> &[Path] { + fn deref(&self) -> &[GenericParam] { &self.0 } } @@ -168,7 +243,7 @@ impl GenericPath { for generic in &mut self.generics { generic.rename_for_config(config, generic_params); } - if !generic_params.contains(&self.path) { + if !generic_params.iter().any(|param| param.name == self.path) { config.export.rename(&mut self.export_name); } } diff --git a/src/bindgen/ir/opaque.rs b/src/bindgen/ir/opaque.rs index 3d0ba4209..4451d4a16 100644 --- a/src/bindgen/ir/opaque.rs +++ b/src/bindgen/ir/opaque.rs @@ -35,7 +35,7 @@ impl OpaqueItem { ) -> Result { Ok(Self::new( path, - GenericParams::new(generics), + GenericParams::load(generics)?, Cfg::append(mod_cfg, Cfg::load(attrs)), AnnotationSet::load(attrs).unwrap_or_else(|_| AnnotationSet::new()), Documentation::load(attrs), diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index b696958aa..be199739d 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -103,7 +103,7 @@ impl Struct { Ok(Struct::new( path, - GenericParams::new(&item.generics), + GenericParams::load(&item.generics)?, fields, has_tag_field, is_enum_variant_body, @@ -370,25 +370,7 @@ impl Item for Struct { library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path, - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); - + let mappings = self.generic_params.call(self.path.name(), generic_values); let monomorph = self.specialize(generic_values, &mappings, library.get_config()); out.insert_struct(library, self, monomorph, generic_values.to_owned()); } diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 033504f9e..cd52fec72 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -804,7 +804,7 @@ impl Type { } } let path = generic.path(); - if !generic_params.contains(path) { + if !generic_params.iter().any(|param| param.name() == path) { if let Some(items) = library.get_items(path) { if !out.items.contains(path) { out.items.insert(path.clone()); diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index f2d6f3b4e..626732e2a 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -37,7 +37,7 @@ impl Typedef { let path = Path::new(item.ident.unraw().to_string()); Ok(Typedef::new( path, - GenericParams::new(&item.generics), + GenericParams::load(&item.generics)?, x, Cfg::append(mod_cfg, Cfg::load(&item.attrs)), AnnotationSet::load(&item.attrs)?, @@ -159,24 +159,7 @@ impl Item for Typedef { library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path, - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); + let mappings = self.generic_params.call(self.path.name(), generic_values); let mangled_path = mangle::mangle_path( &self.path, diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index 61fe80a91..07bd16c58 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -62,7 +62,7 @@ impl Union { Ok(Union::new( path, - GenericParams::new(&item.generics), + GenericParams::load(&item.generics)?, fields, repr.align, tuple_union, @@ -227,24 +227,7 @@ impl Item for Union { library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path, - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); + let mappings = self.generic_params.call(self.path.name(), generic_values); let mangled_path = mangle::mangle_path( &self.path, diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index 804ead033..81681ba17 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -15,8 +15,8 @@ use crate::bindgen::cargo::{Cargo, PackageRef}; use crate::bindgen::config::{Config, ParseConfig}; use crate::bindgen::error::Error; use crate::bindgen::ir::{ - AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams, ItemMap, - OpaqueItem, Path, Static, Struct, Type, Typedef, Union, + AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParam, GenericParams, + ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union, }; use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemFnHelpers}; @@ -425,7 +425,10 @@ impl Parse { pub fn add_std_types(&mut self) { let mut add_opaque = |path: &str, generic_params: Vec<&str>| { let path = Path::new(path); - let generic_params: Vec<_> = generic_params.into_iter().map(Path::new).collect(); + let generic_params: Vec<_> = generic_params + .into_iter() + .map(GenericParam::new_type_param) + .collect(); self.opaque_items.try_insert(OpaqueItem::new( path, GenericParams(generic_params), diff --git a/tests/expectations/const_generics.both.c b/tests/expectations/const_generics.both.c new file mode 100644 index 000000000..78399bc52 --- /dev/null +++ b/tests/expectations/const_generics.both.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +#define TITLE_SIZE 80 + +typedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + +typedef int8_t CArrayString_40[40]; + +typedef struct Book { + CArrayString_TITLE_SIZE title; + CArrayString_40 author; +} Book; + +void root(struct Book *a); diff --git a/tests/expectations/const_generics.both.compat.c b/tests/expectations/const_generics.both.compat.c new file mode 100644 index 000000000..3274454af --- /dev/null +++ b/tests/expectations/const_generics.both.compat.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +#define TITLE_SIZE 80 + +typedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + +typedef int8_t CArrayString_40[40]; + +typedef struct Book { + CArrayString_TITLE_SIZE title; + CArrayString_40 author; +} Book; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct Book *a); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics.c b/tests/expectations/const_generics.c new file mode 100644 index 000000000..eeea09a78 --- /dev/null +++ b/tests/expectations/const_generics.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +#define TITLE_SIZE 80 + +typedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + +typedef int8_t CArrayString_40[40]; + +typedef struct { + CArrayString_TITLE_SIZE title; + CArrayString_40 author; +} Book; + +void root(Book *a); diff --git a/tests/expectations/const_generics.compat.c b/tests/expectations/const_generics.compat.c new file mode 100644 index 000000000..40ded76cb --- /dev/null +++ b/tests/expectations/const_generics.compat.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +#define TITLE_SIZE 80 + +typedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + +typedef int8_t CArrayString_40[40]; + +typedef struct { + CArrayString_TITLE_SIZE title; + CArrayString_40 author; +} Book; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Book *a); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics.cpp b/tests/expectations/const_generics.cpp new file mode 100644 index 000000000..e5157e622 --- /dev/null +++ b/tests/expectations/const_generics.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +constexpr static const uintptr_t TITLE_SIZE = 80; + +template +using CArrayString = int8_t[CAP]; + +struct Book { + CArrayString title; + CArrayString<40> author; +}; + +extern "C" { + +void root(Book *a); + +} // extern "C" diff --git a/tests/expectations/const_generics.pyx b/tests/expectations/const_generics.pyx new file mode 100644 index 000000000..873918610 --- /dev/null +++ b/tests/expectations/const_generics.pyx @@ -0,0 +1,19 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + const uintptr_t TITLE_SIZE # = 80 + + ctypedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + + ctypedef int8_t CArrayString_40[40]; + + ctypedef struct Book: + CArrayString_TITLE_SIZE title; + CArrayString_40 author; + + void root(Book *a); diff --git a/tests/expectations/const_generics.tag.c b/tests/expectations/const_generics.tag.c new file mode 100644 index 000000000..09e47666d --- /dev/null +++ b/tests/expectations/const_generics.tag.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +#define TITLE_SIZE 80 + +typedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + +typedef int8_t CArrayString_40[40]; + +struct Book { + CArrayString_TITLE_SIZE title; + CArrayString_40 author; +}; + +void root(struct Book *a); diff --git a/tests/expectations/const_generics.tag.compat.c b/tests/expectations/const_generics.tag.compat.c new file mode 100644 index 000000000..f764e5b3c --- /dev/null +++ b/tests/expectations/const_generics.tag.compat.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +#define TITLE_SIZE 80 + +typedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + +typedef int8_t CArrayString_40[40]; + +struct Book { + CArrayString_TITLE_SIZE title; + CArrayString_40 author; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct Book *a); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics.tag.pyx b/tests/expectations/const_generics.tag.pyx new file mode 100644 index 000000000..f2c9d7a41 --- /dev/null +++ b/tests/expectations/const_generics.tag.pyx @@ -0,0 +1,19 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + const uintptr_t TITLE_SIZE # = 80 + + ctypedef int8_t CArrayString_TITLE_SIZE[TITLE_SIZE]; + + ctypedef int8_t CArrayString_40[40]; + + cdef struct Book: + CArrayString_TITLE_SIZE title; + CArrayString_40 author; + + void root(Book *a); diff --git a/tests/expectations/const_generics_arrayvec.both.c b/tests/expectations/const_generics_arrayvec.both.c new file mode 100644 index 000000000..e3cc9a076 --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.both.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +typedef struct ArrayVec_____u8__100 { + uint8_t *xs[100]; + uint32_t len; +} ArrayVec_____u8__100; + +int32_t push(struct ArrayVec_____u8__100 *v, uint8_t *elem); diff --git a/tests/expectations/const_generics_arrayvec.both.compat.c b/tests/expectations/const_generics_arrayvec.both.compat.c new file mode 100644 index 000000000..3c382bac5 --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.both.compat.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +typedef struct ArrayVec_____u8__100 { + uint8_t *xs[100]; + uint32_t len; +} ArrayVec_____u8__100; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int32_t push(struct ArrayVec_____u8__100 *v, uint8_t *elem); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics_arrayvec.c b/tests/expectations/const_generics_arrayvec.c new file mode 100644 index 000000000..f7deb7545 --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +typedef struct { + uint8_t *xs[100]; + uint32_t len; +} ArrayVec_____u8__100; + +int32_t push(ArrayVec_____u8__100 *v, uint8_t *elem); diff --git a/tests/expectations/const_generics_arrayvec.compat.c b/tests/expectations/const_generics_arrayvec.compat.c new file mode 100644 index 000000000..3ed7a89d9 --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.compat.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +typedef struct { + uint8_t *xs[100]; + uint32_t len; +} ArrayVec_____u8__100; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int32_t push(ArrayVec_____u8__100 *v, uint8_t *elem); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics_arrayvec.cpp b/tests/expectations/const_generics_arrayvec.cpp new file mode 100644 index 000000000..5e63c744b --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.cpp @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include + +template +struct ArrayVec { + T xs[CAP]; + uint32_t len; +}; + +extern "C" { + +int32_t push(ArrayVec *v, uint8_t *elem); + +} // extern "C" diff --git a/tests/expectations/const_generics_arrayvec.pyx b/tests/expectations/const_generics_arrayvec.pyx new file mode 100644 index 000000000..7e80d25d3 --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.pyx @@ -0,0 +1,13 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + ctypedef struct ArrayVec_____u8__100: + uint8_t *xs[100]; + uint32_t len; + + int32_t push(ArrayVec_____u8__100 *v, uint8_t *elem); diff --git a/tests/expectations/const_generics_arrayvec.tag.c b/tests/expectations/const_generics_arrayvec.tag.c new file mode 100644 index 000000000..1f45babca --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.tag.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +struct ArrayVec_____u8__100 { + uint8_t *xs[100]; + uint32_t len; +}; + +int32_t push(struct ArrayVec_____u8__100 *v, uint8_t *elem); diff --git a/tests/expectations/const_generics_arrayvec.tag.compat.c b/tests/expectations/const_generics_arrayvec.tag.compat.c new file mode 100644 index 000000000..cf45ebcca --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.tag.compat.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +struct ArrayVec_____u8__100 { + uint8_t *xs[100]; + uint32_t len; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int32_t push(struct ArrayVec_____u8__100 *v, uint8_t *elem); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/const_generics_arrayvec.tag.pyx b/tests/expectations/const_generics_arrayvec.tag.pyx new file mode 100644 index 000000000..0b6299087 --- /dev/null +++ b/tests/expectations/const_generics_arrayvec.tag.pyx @@ -0,0 +1,13 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + cdef struct ArrayVec_____u8__100: + uint8_t *xs[100]; + uint32_t len; + + int32_t push(ArrayVec_____u8__100 *v, uint8_t *elem); diff --git a/tests/rust/const_generics.rs b/tests/rust/const_generics.rs new file mode 100644 index 000000000..081b38e24 --- /dev/null +++ b/tests/rust/const_generics.rs @@ -0,0 +1,15 @@ +#[repr(transparent)] +pub struct CArrayString { + pub chars: [i8; CAP], +} + +pub const TITLE_SIZE: usize = 80; + +#[repr(C)] +pub struct Book { + pub title: CArrayString, + pub author: CArrayString<40>, +} + +#[no_mangle] +pub extern "C" fn root(a: *mut Book) {} diff --git a/tests/rust/const_generics_arrayvec.rs b/tests/rust/const_generics_arrayvec.rs new file mode 100644 index 000000000..459ddbcbb --- /dev/null +++ b/tests/rust/const_generics_arrayvec.rs @@ -0,0 +1,17 @@ +#[repr(C)] +pub struct ArrayVec { + // the `len` first elements of the array are initialized + xs: [T; CAP], + len: u32, +} + +#[no_mangle] +pub unsafe extern "C" fn push(v: *mut ArrayVec<*mut u8, 100>, elem: *mut u8) -> i32 { + if (*v).len < 100 { + (*v).xs[(*v).len] = elem; + (*v).len += 1; + 1 + } else { + 0 + } +}