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

[vm/ffi] FfiNative return types treatment inconsistent with asFunction #49518

Open
Tracked by #50565
dcharkes opened this issue Jul 25, 2022 · 6 comments
Open
Tracked by #50565
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi vm-native

Comments

@dcharkes
Copy link
Contributor

dcharkes commented Jul 25, 2022

@FfiNative<Handle Function()>('doesntmatter')
external String? doesntmatter();

https://dart-review.googlesource.com/c/sdk/+/252601/6/pkg/vm/testcases/transformations/ffi/ffinative.dart

asFunction and lookupFunction do not allow the return type to be sticter than Object when the native type is Handle.

The old natives do allow the return type to be stricter than Object.

It would be good to update FfiNatives to be consistent with asFunction, but that would make them inconsistent with old natives.

@dcharkes dcharkes added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. vm-native library-ffi labels Jul 25, 2022
@mkustermann
Copy link
Member

@dcharkes The code you are quoting is not executed but rather there for generating expectation files of what the transformer produces. So there's no issue with this code. It doesn't really matter whether its String? or Object?.

@dcharkes
Copy link
Contributor Author

dcharkes commented Jul 25, 2022

If we add static linking, this will be transformed to an immediate FFI call that does not do a type check on the result value, allowing non String?s to flow there. (I haven't checked if the current transform does add a type check, maybe it also doesn't.)

I've disallowed that behavior in the linked CL, so I had to update the transformer test to make it pass again.

@mkustermann
Copy link
Member

Whether one uses static or dynamic linking shouldn't change any behavior.

Whether we trust the types written by the developer is another question entirely: If user writes Int8 we expect native function takes int8_t. If user writes String? we expect native code to return null | String. We could check explicitly via as-check or not - that's a choice. Irrespective of what choice we make, it will be true for dynamic (e.g. lookupFunction) or static binding (@FfiNative)

Coming back to the test itself: It just checks how the transform handles returning Handle and uses String? but could use any other type.

Maybe I misunderstand the concern here?

@dcharkes
Copy link
Contributor Author

Whether one uses static or dynamic linking shouldn't change any behavior.

For asFunction and lookupFunction we opted to only allow Object as return value. For FfiNative we apparently opted to let the user specify a more narrow type. This is inconsistent. We should fix this inconsistency. Using asFunction or dynamic FfiNative linking shouldn't change any behavior.

Whether we trust the types written by the developer is another question entirely: If user writes Int8 we expect native function takes int8_t. If user writes String? we expect native code to return null | String. We could check explicitly via as-check or not - that's a choice. Irrespective of what choice we make, it will be true for dynamic (e.g. lookupFunction) or static binding (@FfiNative)

Agreed, it is a choice we make. I assume we made that choice consciously for asFunction and lookupFunction when adding Handles. For FfiNatives, we have a function dedicated specifically to this behavior, indicating deviating from asFunction intentionally, but I cannot find any reasoning for this on the CL. (And I didn't catch the differing behavior when reviewing it.)

I propose we stick to asFunction behavior. We can always allow developers to write stricter types later if need be. The other way around would be a breaking change later.

@mkustermann
Copy link
Member

For asFunction and lookupFunction we opted to only allow Object as return value. For FfiNative we apparently opted to
let the user specify a more narrow type. This is inconsistent.

Thanks for the explanation - it's the inconsistency you're concerned about (though that's not related to the test that is quoted in this issue).

I'd like to avoid a situation where we do more checking for @FfiNative as we do for normal natives. So if the ladder doesn't check, I don't think we should check by-default (maybe in --enable-assertions mode).

@dcharkes
Copy link
Contributor Author

it's the inconsistency you're concerned about

Yes, sorry for the confusion. Thanks for helping me clarify. 😄

though that's not related to the test that is quoted in this issue

By removing the inconsistency (by only allowing Object) the test started failing.

I'd like to avoid a situation where we do more checking for @FfiNative as we do for normal natives. So if the ladder doesn't check, I don't think we should check by-default (maybe in --enable-assertions mode).

By only allowing Object, we need no checking.
Of course a subsequent as check by users will introduce a check.

If we want to avoid those user-written as checks, we should change asFunction and lookupFunction to allow stricter return types instead.

@dcharkes dcharkes changed the title [vm/ffi] FfiNative unsound return types [vm/ffi] FfiNative return types treatment inconsistent with asFunction Jul 25, 2022
copybara-service bot pushed a commit that referenced this issue Jul 25, 2022
This CL fixes two issues.

1. `FfiNative`s now check the Dart and native type for compatiblity.
2. Both `FfiNative`, `asFunction`, and `lookupFunction` check the type
   correspondence between native and Dart type with a subtype check of
   the expected Dart type and the provided Dart type. For functions,
   any return type is a subtype of a void type. This is fine for Dart,
   but not for native calls. This CL manually checks the return type
   for void.

This CL does not fix the inconsistency between `asFunction` and
`FfiNative` with regard to allowing more strict return types than
`Object` for `Handle`s
Issue: #49518

Analyzer fixes in follow up CL.

TEST=tests/ffi/vmspecific_static_checks_ffinative_test.dart

Closes: #49471
Change-Id: Ibc7bd6a1a0db59cc5fa5d755d76999fd7e9a06a4
Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-mac-release-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252601
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
copybara-service bot pushed a commit that referenced this issue Jul 25, 2022
This reverts commit 206fdf1.

Reason for revert: Flutter issues are caught by this CL, preventing
Flutter from building.
flutter/flutter#108309

Original change's description:
> [cfe/ffi] Improve FFI call mismatched types compile errors
>
> This CL fixes two issues.
>
> 1. `FfiNative`s now check the Dart and native type for compatiblity.
> 2. Both `FfiNative`, `asFunction`, and `lookupFunction` check the type
>    correspondence between native and Dart type with a subtype check of
>    the expected Dart type and the provided Dart type. For functions,
>    any return type is a subtype of a void type. This is fine for Dart,
>    but not for native calls. This CL manually checks the return type
>    for void.
>
> This CL does not fix the inconsistency between `asFunction` and
> `FfiNative` with regard to allowing more strict return types than
> `Object` for `Handle`s
> Issue: #49518
>
> Analyzer fixes in follow up CL.
>
> TEST=tests/ffi/vmspecific_static_checks_ffinative_test.dart
>
> Closes: #49471
> Change-Id: Ibc7bd6a1a0db59cc5fa5d755d76999fd7e9a06a4
> Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-mac-release-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252601
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Daco Harkes <dacoharkes@google.com>

TBR=kustermann@google.com,dacoharkes@google.com

Change-Id: Id82b129d491adcc94cdd685a0a0f6a43248c71f2
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Issue: #49518
Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-mac-release-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252662
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
copybara-service bot pushed a commit that referenced this issue Aug 1, 2022
This is a reland of commit 206fdf1

Original change's description:
> [cfe/ffi] Improve FFI call mismatched types compile errors
>
> This CL fixes two issues.
>
> 1. `FfiNative`s now check the Dart and native type for compatiblity.
> 2. Both `FfiNative`, `asFunction`, and `lookupFunction` check the type
>    correspondence between native and Dart type with a subtype check of
>    the expected Dart type and the provided Dart type. For functions,
>    any return type is a subtype of a void type. This is fine for Dart,
>    but not for native calls. This CL manually checks the return type
>    for void.
>
> This CL does not fix the inconsistency between `asFunction` and
> `FfiNative` with regard to allowing more strict return types than
> `Object` for `Handle`s
> Issue: #49518
>
> Analyzer fixes in follow up CL.
>
> TEST=tests/ffi/vmspecific_static_checks_ffinative_test.dart
>
> Closes: #49471
> Change-Id: Ibc7bd6a1a0db59cc5fa5d755d76999fd7e9a06a4
> Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-mac-release-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252601
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Daco Harkes <dacoharkes@google.com>

TEST=tests/ffi/vmspecific_static_checks_ffinative_test.dart

Change-Id: Ic1efba45ae8ff2585fc67fdf63c653ce090d0337
Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try,analyzer-mac-release-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252663
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi vm-native
Projects
None yet
Development

No branches or pull requests

2 participants