Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The ability to generate trait methods using types #1054

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

PuffyWithEyes
Copy link

When writing similar code now:

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
    }
}

Incorrect code will be generated, looking something like this:

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {
  uintptr_t dummy;
} Dummy0;

typedef struct {
  uintptr_t dummy;
} Dummy1;

DummyOut dummy_Dummy0(Dummy0 self, DummyIn in_);

DummyOut dummy_Dummy1(Dummy1 self, DummyIn in_);

My fix allows the code to be generated correctly:

#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);

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
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?

Err(..) => continue,
};

for (ident, ty) in &impls_with_assoc_ty {
Copy link
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
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

@PuffyWithEyes PuffyWithEyes requested a review from emilio March 7, 2025 12:27
@PuffyWithEyes
Copy link
Author

Perhaps this execution will be acceptable...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants