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

Add an alternate path determining the arguments for a function. #1508

Merged
merged 1 commit into from
Feb 3, 2019

Conversation

flowbish
Copy link
Contributor

This fixes the issue seen in #1500 where function pointers as a return type have their parameters incorrectly generated.

This issue was happening because the cursor was being used to determine the arguments for a function prototype. This is fine, but function prototypes in the return position have no cursor associated with them. This would cause the code to reuse the cursor from the function returning it and copy its parameters. Thus int (*func(void))(int, int) would be parsed as int (*func(void))(void).

This causes issues with some Objective C tests for reasons I don't quite understand, so it's not yet ready. I'd love some input on this, or maybe even for someone to adopt this patch if they really feel so motivated.

@highfive
Copy link

warning Warning warning

  • These commits modify unsafe code. Please review it carefully!

Copy link
Contributor

@emilio emilio left a comment

Choose a reason for hiding this comment

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

Thanks for looking at this! Can you describe what the objc failures are?

CXCursor_NoDeclFound => {
ty
.args()
.unwrap()
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, unwraping here looks somewhat fishy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, very much.


let ret = Item::from_ty_or_ref(
ty_ret_type,
ty_ret_type.declaration(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, so I see how this works, but it is a bit fishy to pass the declaration here just to match it from NoDeclFound afterwards. I suspect this can break other stuff but I'd need to think about what...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right about that, I think that this is the source of the test failures below.

@flowbish
Copy link
Contributor Author

Thanks for taking a look at this. I would love some help restructuring this and getting this PR into a good state. It would be great if you could take a look at the test failures, as I don't really understand what's going on there.

@flowbish
Copy link
Contributor Author

flowbish commented Feb 1, 2019

I updated the PR with another shot at fixing this – I feel a bit more confident in the code changes this time.

As a side effect, it seems to have fixed a previously-broken test: objc_property_fnptr.h.

Copy link
Contributor

@emilio emilio left a comment

Choose a reason for hiding this comment

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

Thanks, this change makes much more sense to me! Looks good, just some nits / suggestions, if you want. Looks good otherwise!

src/clang.rs Outdated Show resolved Hide resolved
src/clang.rs Outdated Show resolved Hide resolved
src/clang.rs Outdated Show resolved Hide resolved
src/ir/function.rs Outdated Show resolved Hide resolved
src/ir/function.rs Show resolved Hide resolved
) -> Vec<(Option<String>, TypeId)> {
match (cursor.args(), ty.args()) {
(Some(cursor_args), Some(ty_args)) => {
ty_args.iter().enumerate().map(|(i, ty)| {
Copy link
Contributor

Choose a reason for hiding this comment

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

So, what about the following instead, which could be much shorter:

let args_for_names = cursor.args().unwrap();
let ty_args = ty.args();
let ty_args = ty_args.as_ref().unwrap_or(&args_for_names);

// Write the loop only once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to rewrite this a few different ways but found everything unsatisfactory. Cursor::args() and Type::args() return different types and I haven't figured out a good way in Rust to work with iterators of different concrete types well. Definitely open to suggestions!

Copy link
Contributor

Choose a reason for hiding this comment

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

Meh, this doesn't look too bad as-is. Thanks again for looking into this!

@@ -353,28 +378,14 @@ impl FunctionSig {
ty.declaration()
};

let mut args: Vec<_> = match cursor.kind() {
let mut args = match cursor.kind() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this needs a small rebase (using kind instead of cursor.kind()).

) -> Vec<(Option<String>, TypeId)> {
match (cursor.args(), ty.args()) {
(Some(cursor_args), Some(ty_args)) => {
ty_args.iter().enumerate().map(|(i, ty)| {
Copy link
Contributor

Choose a reason for hiding this comment

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

Meh, this doesn't look too bad as-is. Thanks again for looking into this!

…signatures.

This fixes the issue seen in rust-lang#1500 where function
pointers as a return type have their parameters incorrectly generated.

This also fixes a broken test case, objc_property_fnptr, as its types
are now generated correctly.
@emilio
Copy link
Contributor

emilio commented Feb 3, 2019

Just did the rebase myself. Thanks!

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

Successfully merging this pull request may close these issues.

None yet

3 participants