Skip to content

Commit 069e617

Browse files
dcharkesCommit Queue
authored and
Commit Queue
committed
[analyzer/ffi] Fix Unwrap typed data error messages
Fixes issues reported by: TEST=pkg/analyzer/test/verify_diagnostics_test.dart * Fixes error messages on asFunction. * Fixes validation by introducing Uint8List to mock sdk. * Removes unused typed_data import in example snippet. * Fixes error locations in example snippets Bug: #44589 Change-Id: I82261eea5e55cbafa686865a92131a449a7642f5 Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-try,pkg-mac-release-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/340921 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent d548c07 commit 069e617

File tree

5 files changed

+151
-6
lines changed

5 files changed

+151
-6
lines changed

pkg/analyzer/lib/src/generated/ffi_verifier.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
910910
}
911911
_validateFfiTypedDataUnwrapping(
912912
F,
913-
T,
913+
TPrime,
914914
errorNode,
915915
isLeaf: isLeaf,
916916
isCall: true,
@@ -1086,6 +1086,11 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
10861086
int i = 0;
10871087
final nativeParamTypes = nativeType.normalParameterTypes.flattenVarArgs();
10881088
for (final dartParam in dartType.normalParameterTypes) {
1089+
if (i >= nativeParamTypes.length) {
1090+
// Cascading error as not the same amount of arguments.
1091+
// Already results in an error earlier.
1092+
return;
1093+
}
10891094
final nativeParam = nativeParamTypes[i];
10901095
i++;
10911096
if (dartParam.isTypedData && nativeParam.isPointer) {

pkg/analyzer/lib/src/test_utilities/mock_sdk.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,10 @@ final MockSdkLibrary _LIB_TYPED_DATA = MockSdkLibrary(
13781378
'''
13791379
library dart.typed_data;
13801380
1381+
abstract final class Uint8List {
1382+
external factory Uint8List(int length);
1383+
}
1384+
13811385
abstract final class Int8List {
13821386
external factory Int8List(int length);
13831387
}

pkg/analyzer/messages.yaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19859,7 +19859,7 @@ FfiCode:
1985919859
import 'dart:typed_data';
1986019860

1986119861
void f(Pointer<NativeFunction<Void Function(Pointer<Uint8>)>> p) {
19862-
[!p.asFunction<void Function(Uint8List)>()!];
19862+
p.asFunction<[!void Function(Uint8List)!]>();
1986319863
}
1986419864
```
1986519865

@@ -19905,7 +19905,7 @@ FfiCode:
1990519905
import 'dart:typed_data';
1990619906

1990719907
void f(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
19908-
[!p.asFunction<Uint8List Function()>()!];
19908+
p.asFunction<[!Uint8List Function()!]>();
1990919909
}
1991019910
```
1991119911

@@ -19915,7 +19915,6 @@ FfiCode:
1991519915

1991619916
```dart
1991719917
import 'dart:ffi';
19918-
import 'dart:typed_data';
1991919918

1992019919
void f(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
1992119920
p.asFunction<Pointer<Uint8> Function()>();
@@ -19949,7 +19948,7 @@ FfiCode:
1994919948
void f(Uint8List i) {}
1995019949

1995119950
void g() {
19952-
Pointer.fromFunction<Void Function(Pointer<Uint8>)>(f);
19951+
Pointer.fromFunction<Void Function(Pointer<Uint8>)>([!f!]);
1995319952
}
1995419953
```
1995519954

@@ -19959,7 +19958,6 @@ FfiCode:
1995919958

1996019959
```dart
1996119960
import 'dart:ffi';
19962-
import 'dart:typed_data';
1996319961

1996419962
void f(Pointer<Uint8> i) {}
1996519963

pkg/analyzer/tool/diagnostics/diagnostics.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,6 +1918,90 @@ extension [!mixin!] on int {}
19181918

19191919
Choose a different name for the declaration.
19201920

1921+
### callback_must_not_use_typed_data
1922+
1923+
_FFI callbacks can't take typed data arguments or return value._
1924+
1925+
#### Description
1926+
1927+
The analyzer produces this diagnostic when an invocation of
1928+
`Pointer.fromFunction`, one of`NativeCallable`'s constructors has a
1929+
typed data argument or return value."
1930+
1931+
Typed data unwrapping is only supported on arguments for leaf FFI calls.
1932+
1933+
For more information about FFI, see [C interop using dart:ffi][ffi].
1934+
1935+
#### Example
1936+
1937+
The following code produces this diagnostic because the parameter type
1938+
of `g` is a typed data.
1939+
1940+
{% prettify dart tag=pre+code %}
1941+
import 'dart:ffi';
1942+
import 'dart:typed_data';
1943+
1944+
void f(Uint8List i) {}
1945+
1946+
void g() {
1947+
Pointer.fromFunction<Void Function(Pointer<Uint8>)>([!f!]);
1948+
}
1949+
{% endprettify %}
1950+
1951+
#### Common fixes
1952+
1953+
Use the `Pointer` type instead:
1954+
1955+
{% prettify dart tag=pre+code %}
1956+
import 'dart:ffi';
1957+
1958+
void f(Pointer<Uint8> i) {}
1959+
1960+
void g() {
1961+
Pointer.fromFunction<Void Function(Pointer<Uint8>)>(f);
1962+
}
1963+
{% endprettify %}
1964+
1965+
### call_must_not_return_typed_data
1966+
1967+
_FFI calls can't return typed data._
1968+
1969+
#### Description
1970+
1971+
The analyzer produces this diagnostic when the return type of
1972+
`Pointer.asFunction`, `DynamicLibrary.lookupFunction`, or
1973+
`@Native` is a typed data.
1974+
1975+
Typed data unwrapping is only supported on arguments for leaf FFI calls.
1976+
1977+
For more information about FFI, see [C interop using dart:ffi][ffi].
1978+
1979+
#### Example
1980+
1981+
The following code produces this diagnostic because the dart function
1982+
signature contains a typed data, but the `isLeaf` argument is `false`:
1983+
1984+
{% prettify dart tag=pre+code %}
1985+
import 'dart:ffi';
1986+
import 'dart:typed_data';
1987+
1988+
void f(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
1989+
p.asFunction<[!Uint8List Function()!]>();
1990+
}
1991+
{% endprettify %}
1992+
1993+
#### Common fixes
1994+
1995+
Use the `Pointer` type instead:
1996+
1997+
{% prettify dart tag=pre+code %}
1998+
import 'dart:ffi';
1999+
2000+
void f(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
2001+
p.asFunction<Pointer<Uint8> Function()>();
2002+
}
2003+
{% endprettify %}
2004+
19212005
### case_block_not_terminated
19222006

19232007
_The last statement of the 'case' should be 'break', 'continue', 'rethrow',
@@ -15167,6 +15251,52 @@ class A {
1516715251
class B implements A {}
1516815252
{% endprettify %}
1516915253

15254+
### non_leaf_call_must_not_take_typed_data
15255+
15256+
_FFI non-leaf calls can't take typed data arguments._
15257+
15258+
#### Description
15259+
15260+
The analyzer produces this diagnostic when the value of the `isLeaf`
15261+
argument of `Pointer.asFunction`, `DynamicLibrary.lookupFunction`, or
15262+
`@Native` is `false` and the Dart function signature contains a typed
15263+
data parameter.
15264+
15265+
Typed data unwrapping is only supported on arguments for leaf FFI calls.
15266+
15267+
For more information about FFI, see [C interop using dart:ffi][ffi].
15268+
15269+
#### Example
15270+
15271+
The following code produces this diagnostic because the dart function
15272+
signature contains a typed data, but the `isLeaf` argument is `false`:
15273+
15274+
{% prettify dart tag=pre+code %}
15275+
import 'dart:ffi';
15276+
import 'dart:typed_data';
15277+
15278+
void f(Pointer<NativeFunction<Void Function(Pointer<Uint8>)>> p) {
15279+
p.asFunction<[!void Function(Uint8List)!]>();
15280+
}
15281+
{% endprettify %}
15282+
15283+
#### Common fixes
15284+
15285+
If the function has at least one typed data parameter, then add
15286+
the `isLeaf` argument:
15287+
15288+
{% prettify dart tag=pre+code %}
15289+
import 'dart:ffi';
15290+
import 'dart:typed_data';
15291+
15292+
void f(Pointer<NativeFunction<Void Function(Pointer<Uint8>)>> p) {
15293+
p.asFunction<void Function(Uint8List)>(isLeaf: true);
15294+
}
15295+
{% endprettify %}
15296+
15297+
If the function also uses `Handle`s, then it must be non-leaf. In That
15298+
case use `Pointer`s instead of typed data.
15299+
1517015300
### non_native_function_type_argument_to_pointer
1517115301

1517215302
_Can't invoke 'asFunction' because the function signature '{0}' for the pointer

tests/ffi/vmspecific_static_checks_typeddata_test.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,12 @@ void g2() {
9090
// [analyzer] COMPILE_TIME_ERROR.CALLBACK_MUST_NOT_USE_TYPED_DATA
9191
}
9292

93+
void foo1(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
94+
p.asFunction<Uint8List Function()>(isLeaf: true);
95+
//^
96+
// [cfe] FFI calls can't return typed data.
97+
// ^^^^^^^^^^^^^^^^^^^^
98+
// [analyzer] COMPILE_TIME_ERROR.CALL_MUST_NOT_RETURN_TYPED_DATA
99+
}
100+
93101
// TODO(https://dartbug.com/54181): Write negative tests for @Natives.

0 commit comments

Comments
 (0)