Version 2.19.0-51.0.dev
Merge commit '48693c6b3df256eb082bc51e7b5856d23bd7ce4a' into 'dev'
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 43b4217..920c786 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -9,6 +9,7 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/error/ffi_code.dart';
@@ -341,6 +342,7 @@
}
var ffiParameterTypes = ffiSignature.normalParameterTypes;
+ var ffiParameters = ffiSignature.parameters;
if (declarationElement is MethodElement && !declarationElement.isStatic) {
// Instance methods must have the receiver as an extra parameter in the
@@ -366,6 +368,7 @@
}
ffiParameterTypes = ffiParameterTypes.sublist(1);
+ ffiParameters = ffiParameters.sublist(1);
} else {
// Number of parameters in the FfiNative annotation must match the
// annotated declaration.
@@ -391,6 +394,27 @@
}
}
}
+
+ final dartType = declarationElement.type;
+ final nativeType = FunctionTypeImpl(
+ typeFormals: ffiSignature.typeFormals,
+ parameters: ffiParameters,
+ returnType: ffiSignature.returnType,
+ nullabilitySuffix: ffiSignature.nullabilitySuffix,
+ );
+ if (!_isValidFfiNativeFunctionType(nativeType)) {
+ _errorReporter.reportErrorForNode(
+ FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
+ errorNode,
+ [nativeType, 'FfiNative']);
+ return;
+ }
+ if (!_validateCompatibleFunctionTypes(dartType, nativeType,
+ nativeFieldWrappersAsPointer: true, allowStricterReturn: true)) {
+ _errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_SUBTYPE, errorNode,
+ [nativeType, dartType, 'FfiNative']);
+ return;
+ }
}
}
@@ -777,7 +801,11 @@
/// Validates that the given [nativeType] is, when native types are converted
/// to their Dart equivalent, a subtype of [dartType].
bool _validateCompatibleFunctionTypes(
- DartType dartType, DartType nativeType) {
+ DartType dartType,
+ DartType nativeType, {
+ bool nativeFieldWrappersAsPointer = false,
+ bool allowStricterReturn = false,
+ }) {
// We require both to be valid function types.
if (dartType is! FunctionType ||
dartType.isDartCoreFunction ||
@@ -804,14 +832,26 @@
// Validate that the return types are compatible.
if (!_validateCompatibleNativeType(
- dartType.returnType, nativeType.returnType, false)) {
- return false;
+ dartType.returnType, nativeType.returnType)) {
+ // TODO(http://dartbug.com/49518): Fix inconsistency between `FfiNative`
+ // and `asFunction`.
+ if (!allowStricterReturn) {
+ return false;
+ } else if (!_validateCompatibleNativeType(
+ dartType.returnType, nativeType.returnType,
+ checkCovariance: true)) {
+ return false;
+ }
}
// Validate that the parameter types are compatible.
for (int i = 0; i < parameterCount; ++i) {
- if (!_validateCompatibleNativeType(dartType.normalParameterTypes[i],
- nativeType.normalParameterTypes[i], true)) {
+ if (!_validateCompatibleNativeType(
+ dartType.normalParameterTypes[i],
+ nativeType.normalParameterTypes[i],
+ checkCovariance: true,
+ nativeFieldWrappersAsPointer: nativeFieldWrappersAsPointer,
+ )) {
return false;
}
}
@@ -824,7 +864,11 @@
/// [dartType] the latter is a subtype of the former if
/// [checkCovariance].
bool _validateCompatibleNativeType(
- DartType dartType, DartType nativeType, bool checkCovariance) {
+ DartType dartType,
+ DartType nativeType, {
+ bool checkCovariance = false,
+ bool nativeFieldWrappersAsPointer = false,
+ }) {
final nativeReturnType = _primitiveNativeType(nativeType);
if (nativeReturnType == _PrimitiveDartType.int ||
(nativeType is InterfaceType &&
@@ -837,12 +881,22 @@
return dartType.isDartCoreBool;
} else if (nativeReturnType == _PrimitiveDartType.void_) {
return dartType.isVoid;
+ } else if (dartType.isVoid) {
+ // Don't allow other native subtypes if the Dart return type is void.
+ return nativeReturnType == _PrimitiveDartType.void_;
} else if (nativeReturnType == _PrimitiveDartType.handle) {
InterfaceType objectType = typeSystem.objectStar;
return checkCovariance
? /* everything is subtype of objectStar */ true
: typeSystem.isSubtypeOf(objectType, dartType);
} else if (dartType is InterfaceType && nativeType is InterfaceType) {
+ if (nativeFieldWrappersAsPointer &&
+ _extendsNativeFieldWrapperClass1(dartType)) {
+ // Must be `Pointer<Void>`, `Handle` already checked above.
+ return nativeType.isPointer &&
+ _primitiveNativeType(nativeType.typeArguments.single) ==
+ _PrimitiveDartType.void_;
+ }
return checkCovariance
? typeSystem.isSubtypeOf(dartType, nativeType)
: typeSystem.isSubtypeOf(nativeType, dartType);
@@ -1015,7 +1069,7 @@
} else {
Expression e = node.argumentList.arguments[1];
var eType = e.typeOrThrow;
- if (!_validateCompatibleNativeType(eType, R, true)) {
+ if (!_validateCompatibleNativeType(eType, R, checkCovariance: true)) {
_errorReporter.reportErrorForNode(
FfiCode.MUST_BE_A_SUBTYPE, e, [eType, R, 'fromFunction']);
}
diff --git a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
index 9b23e47..638d75f 100644
--- a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
@@ -50,7 +50,7 @@
await assertErrorsInCode(r'''
import 'dart:ffi';
@FfiNative<Int8 Function(Int64)>('DoesntMatter', isLeaf:true)
-external int doesntMatter(int);
+external int doesntMatter(int x);
''', []);
}
@@ -87,6 +87,26 @@
]);
}
+ test_FfiNativeNonFfiParameter() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<IntPtr Function(int)>('doesntmatter')
+external int nonFfiParameter(int v);
+''', [
+ error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 19, 85),
+ ]);
+ }
+
+ test_FfiNativeNonFfiReturnType() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<double Function(IntPtr)>('doesntmatter')
+external double nonFfiReturnType(int v);
+''', [
+ error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 19, 92),
+ ]);
+ }
+
test_FfiNativeTooFewParameters() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@@ -106,4 +126,34 @@
error(FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS, 19, 95),
]);
}
+
+ test_FfiNativeVoidReturn() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function(Uint32, Uint32, Handle)>('doesntmatter')
+external void voidReturn(int width, int height, Object outImage);
+''', [
+ error(FfiCode.MUST_BE_A_SUBTYPE, 19, 133),
+ ]);
+ }
+
+ test_FfiNativeWrongFfiParameter() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<IntPtr Function(Double)>('doesntmatter')
+external int wrongFfiParameter(int v);
+''', [
+ error(FfiCode.MUST_BE_A_SUBTYPE, 19, 90),
+ ]);
+ }
+
+ test_FfiNativeWrongFfiReturnType() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<IntPtr Function(IntPtr)>('doesntmatter')
+external double wrongFfiReturnType(int v);
+''', [
+ error(FfiCode.MUST_BE_A_SUBTYPE, 19, 94),
+ ]);
+ }
}
diff --git a/tests/ffi/vmspecific_static_checks_ffinative_test.dart b/tests/ffi/vmspecific_static_checks_ffinative_test.dart
index 24bd3d4..72549f7 100644
--- a/tests/ffi/vmspecific_static_checks_ffinative_test.dart
+++ b/tests/ffi/vmspecific_static_checks_ffinative_test.dart
@@ -80,18 +80,14 @@
@FfiNative<Void Function({Double})>('doesntmatter') //# 13: compile-time error
external static int badNamedParam(); //# 13: compile-time error
-// TODO(https://dartbug.com/49412): Implement in analyzer.
@FfiNative<IntPtr Function(Double)>('doesntmatter') //# 14: compile-time error
external int wrongFfiParameter(int v); //# 14: compile-time error
-// TODO(https://dartbug.com/49412): Implement in analyzer.
@FfiNative<IntPtr Function(IntPtr)>('doesntmatter') //# 15: compile-time error
external double wrongFfiReturnType(int v); //# 15: compile-time error
-// TODO(https://dartbug.com/49412): Implement in analyzer.
-@FfiNative<int Function(Double)>('doesntmatter') //# 16: compile-time error
+@FfiNative<IntPtr Function(int)>('doesntmatter') //# 16: compile-time error
external int nonFfiParameter(int v); //# 16: compile-time error
-// TODO(https://dartbug.com/49412): Implement in analyzer.
@FfiNative<double Function(IntPtr)>('doesntmatter') //# 17: compile-time error
external double nonFfiReturnType(int v); //# 17: compile-time error
diff --git a/tools/VERSION b/tools/VERSION
index dc85efc..6265d32 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 19
PATCH 0
-PRERELEASE 50
+PRERELEASE 51
PRERELEASE_PATCH 0
\ No newline at end of file