Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions src/bindgen/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,13 +533,15 @@ impl Parse {
self.load_syn_ty(crate_name, mod_cfg, item);
}
syn::Item::Impl(ref item_impl) => {
let has_assoc_const = item_impl
.items
.iter()
.any(|item| matches!(item, syn::ImplItem::Const(_)));
if has_assoc_const {
impls_with_assoc_consts.push(item_impl);
}
let mut impls_with_assoc_ty = Vec::new();

item_impl.items.iter().for_each(|item| {
if matches!(item, syn::ImplItem::Const(_)) {
impls_with_assoc_consts.push(item_impl);
} else if let syn::ImplItem::Type(t) = item {
impls_with_assoc_ty.push((&t.ident, &t.ty));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This array seems wrong, it's not storing impls, but ident and types, so maybe just call the vector associated_tys or so?

}
});

if let syn::Type::Path(ref path) = *item_impl.self_ty {
if let Some(type_name) = path.path.get_ident() {
Expand All @@ -549,13 +551,46 @@ impl Parse {
}
_ => None,
}) {
let mut method = method.clone();
let out = match Type::load_from_output(&method.sig.output) {
Ok((out, ..)) => out,
Err(..) => continue,
};

for (ident, ty) in &impls_with_assoc_ty {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'm a bit confused as to what are you trying to do here. Can you add some comments to clarify?

Let's see if I get this right... When you see a method, you go through the return and argument types, and try to fix them up by matching with the associated types.

I don't think this is quite the right thing to do. I guess this does work for very simple cases, but:

  • At the very least you should do this recursively.
  • I think ideally, we emit the right thing which would be something like:
typedef void Dummy0_DummyTrait_DummyIn;
// etc

And then load_syn_method just knows about associated paths with Self and deals with that. Doing this mapping on the syn types seems a bit funky / sketchy at least.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emilio in my first trial version, the implementation was approximately the way you described, but I thought that it would be excessive. If you think that it will be better - I will do so

let ident = ident.to_string();

if let (Some(out_name), syn::ReturnType::Type(_, t)) =
(out.get_root_path(), &mut method.sig.output)
{
if ident == out_name.to_string() {
*t = Box::new((*ty).clone());
}
}

method.sig.inputs.iter_mut().for_each(|arg| {
if let syn::FnArg::Typed(t) = arg {
let attr_ty = match Type::load(&t.ty) {
Ok(Some(t)) => t,
_ => return,
};

if let Some(attr_ty) = attr_ty.get_root_path() {
if ident == attr_ty.to_string() {
t.ty = Box::new((*ty).clone());
}
}
}
});
}

self.load_syn_method(
config,
binding_crate_name,
crate_name,
mod_cfg,
&Path::new(type_name.unraw().to_string()),
method,
&method,
)
}
}
Expand Down
4 changes: 4 additions & 0 deletions tests/expectations-symbols/traits_type.c.sym
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
dummy_Dummy0;
dummy_Dummy1;
};
16 changes: 16 additions & 0 deletions tests/expectations/traits_type.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {
uintptr_t dummy;
} Dummy0;

typedef struct {
uintptr_t dummy;
} Dummy1;

Dummy0 dummy_Dummy0(Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(Dummy1 self);
24 changes: 24 additions & 0 deletions tests/expectations/traits_type.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {
uintptr_t dummy;
} Dummy0;

typedef struct {
uintptr_t dummy;
} Dummy1;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

Dummy0 dummy_Dummy0(Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(Dummy1 self);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
21 changes: 21 additions & 0 deletions tests/expectations/traits_type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

struct Dummy0 {
uintptr_t dummy;
};

struct Dummy1 {
uintptr_t dummy;
};

extern "C" {

Dummy0 dummy_Dummy0(Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(Dummy1 self);

} // extern "C"
17 changes: 17 additions & 0 deletions tests/expectations/traits_type.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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 Dummy0:
uintptr_t dummy;

ctypedef struct Dummy1:
uintptr_t dummy;

Dummy0 dummy_Dummy0(Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(Dummy1 self);
16 changes: 16 additions & 0 deletions tests/expectations/traits_type_both.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Dummy0 {
uintptr_t dummy;
} Dummy0;

typedef struct Dummy1 {
uintptr_t dummy;
} Dummy1;

struct Dummy0 dummy_Dummy0(struct Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(struct Dummy1 self);
24 changes: 24 additions & 0 deletions tests/expectations/traits_type_both.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Dummy0 {
uintptr_t dummy;
} Dummy0;

typedef struct Dummy1 {
uintptr_t dummy;
} Dummy1;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

struct Dummy0 dummy_Dummy0(struct Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(struct Dummy1 self);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
16 changes: 16 additions & 0 deletions tests/expectations/traits_type_tag.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

struct Dummy0 {
uintptr_t dummy;
};

struct Dummy1 {
uintptr_t dummy;
};

struct Dummy0 dummy_Dummy0(struct Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(struct Dummy1 self);
24 changes: 24 additions & 0 deletions tests/expectations/traits_type_tag.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

struct Dummy0 {
uintptr_t dummy;
};

struct Dummy1 {
uintptr_t dummy;
};

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

struct Dummy0 dummy_Dummy0(struct Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(struct Dummy1 self);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
17 changes: 17 additions & 0 deletions tests/expectations/traits_type_tag.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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 Dummy0:
uintptr_t dummy;

cdef struct Dummy1:
uintptr_t dummy;

Dummy0 dummy_Dummy0(Dummy0 self, uintptr_t in_);

int32_t dummy_Dummy1(Dummy1 self);
38 changes: 38 additions & 0 deletions tests/rust/traits_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
pub trait DummyTrait {
type DummyIn;
type DummyOut;

extern "C" fn dummy(self, in_: Self::DummyIn) -> Self::DummyOut;
}

#[repr(C)]
pub struct Dummy0 {
dummy: usize,
}

impl DummyTrait for Dummy0 {
type DummyIn = usize;
type DummyOut = Self;

#[unsafe(export_name = "dummy_Dummy0")]
extern "C" fn dummy(self, in_: Self::DummyIn) -> Self::DummyOut {
Self {
dummy: in_,
}
}
}

#[repr(C)]
pub struct Dummy1 {
dummy: usize
}

impl DummyTrait for Dummy1 {
type DummyIn = ();
type DummyOut = i32;

#[unsafe(export_name = "dummy_Dummy1")]
extern "C" fn dummy(self, in_: Self::DummyIn) -> Self::DummyOut {
0
}
}