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 package name to RustBufferI if it needs it #44

Merged
merged 2 commits into from
Mar 14, 2024
Merged

Conversation

kegsay
Copy link
Contributor

@kegsay kegsay commented Mar 8, 2024

Fixes #43

@arg0d
Copy link
Collaborator

arg0d commented Mar 12, 2024

I'm trying to wrap my head around when does this happen. Is there a simple way to repro this inside the tests? I think there are already some tests for "external" types ext_types_test.go.

@kegsay
Copy link
Contributor Author

kegsay commented Mar 12, 2024

It only happens on async functions when the value being returned is in another package. In that case, both packages have RustBufferI types and the compiler complains as the generated code uses both types when it should be choosing one and sticking with it.

There isn't a simple way to reproduce the test due to #45 - I could probably write a test in a completely separate test package and then go test that?

@arg0d
Copy link
Collaborator

arg0d commented Mar 13, 2024

I can reproduce #45, but this PR does not seem to do anything for #45, I still get the same error with these changes.

@kegsay
Copy link
Contributor Author

kegsay commented Mar 13, 2024

It won't do anything for #45. This PR is fixing #43.

@arg0d
Copy link
Collaborator

arg0d commented Mar 13, 2024

Oh sorry, I misunderstood your previous comment. So #43 only happens with async code? I would really appreciate to have either an actual test case for this, or at least explain the offending configuration in a comment above maybe_namespace. If left untested/unexplained, this type of change is very likely to be lost with future refactorings/uniffi-rs version updates.

#45 is a runtime error, but #43 is a compile time error, so I think it should be possible to reproduce #43 despite the existence of #45.

@kegsay
Copy link
Contributor Author

kegsay commented Mar 14, 2024

Yup, I have a working regression test now in a new package uniffi_go_issue43. The test itself requires #46 as it uses that as the external package. It just does:

#[uniffi::export]
async fn get_async_external_type() -> uniffi_go_issue45::Record {
    uniffi_go_issue45::Record {
        id: "foo".to_string(),
        tag: "bar".to_string(),
    }
}

which requires this PR to produce code that compiles, which produces a completeFunc of:

		func(handle *C.void, status *C.RustCallStatus) issue45.RustBufferI {
			// completeFunc
			return C.ffi_uniffi_go_issue43_rust_future_complete_rust_buffer(unsafe.Pointer(handle), status)
		},

whereas without #44 it would just be func(handle *C.void, status *C.RustCallStatus) RustBufferI { which compile errors on the liftFunc: type func(rb issue45.RustBufferI) issue45.Record of issue45.FfiConverterTypeRecordINSTANCE.Lift does not match inferred type func(RustBufferI) U for func(T) Ucompiler[CannotInferTypeArgs](https://pkg.go.dev/golang.org/x/tools/internal/typesinternal#CannotInferTypeArgs).

@kegsay
Copy link
Contributor Author

kegsay commented Mar 14, 2024

Rebased as #46 landed. It should be pretty clear now!

@arg0d
Copy link
Collaborator

arg0d commented Mar 14, 2024

Nice work!

I finally understand why this error only happens with async 😅 My initial reaction was that this should also happen with regular functions, e.g.

func GetAsyncExternalType() issue45.Record {
	return issue45.FfiConverterTypeRecordINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI {
		return C.uniffi_uniffi_go_issue43_fn_func_get_async_external_type(_uniffiStatus)
	}))
}

In this example there is also a type mismatch between what issue45.FfiConverterTypeRecordINSTANCE.Lift expects, and what rustCall returns. But I assume in this case Go's interface duck typing kicks in, and allows an implicit conversion from issue43.RustBufferI into issue45.RustBufferI.

Contrast that with async code, where issue43.RustBufferI and issue45.RustBufferI are parameters to a generic function func uniffiRustCallAsyncWithResult[T any, U any] .., and interface duck typing rules do not apply - compiler expects identical types for generic parameters.

bindgen/src/gen_go/mod.rs Outdated Show resolved Hide resolved
Signed-off-by: Kegan Dougal <[email protected]>
Copy link
Collaborator

@arg0d arg0d left a comment

Choose a reason for hiding this comment

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

Nice work, thanks for contributing!

@arg0d arg0d merged commit 62738f9 into NordSecurity:main Mar 14, 2024
3 checks passed
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.

Multiple crates sharing RustBufferI doesn't compile
2 participants