[VM] Adds error for leaf FfiNative w. Handle

This adds an analyzer compile-time error for using Handles
with leaf call FfiNatives.
This same error already exists in the transforms.
(See `_ensureLeafCallDoesNotUseHandles(..)`)

Bug: https://github.com/dart-lang/sdk/issues/46625
Change-Id: Iec52d5df6dd346a25ef2976e552cf1cb58c17ff6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207460
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Clement Skau <cskau@google.com>
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index ae2d2bc7..73cc7f3 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -277,12 +277,26 @@
 
     for (Annotation annotation in annotations) {
       if (annotation.name.name == _ffiNativeName) {
+        // All FFI Natives must be static.
         final isStatic = (node is FunctionDeclaration) ||
             ((node is MethodDeclaration) && node.isStatic);
         if (!isStatic) {
           _errorReporter.reportErrorForNode(
               FfiCode.FFI_NATIVE_ONLY_STATIC, node);
         }
+        // Leaf call FFI Natives can't use Handles.
+        ArgumentList? argumentList = annotation.arguments;
+        if (argumentList != null) {
+          NodeList<Expression> arguments = argumentList.arguments;
+          TypeArgumentList? typeArgumentList = annotation.typeArguments;
+          if (typeArgumentList != null) {
+            NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
+            if (typeArguments.isNotEmpty && typeArguments[0].type != null) {
+              _validateFfiLeafCallUsesNoHandles(
+                  arguments, typeArguments[0].type!, node);
+            }
+          }
+        }
       }
     }
   }
@@ -530,7 +544,8 @@
         _errorReporter.reportErrorForNode(
             FfiCode.MUST_BE_A_SUBTYPE, node, [TPrime, F, 'asFunction']);
       }
-      _validateFfiLeafCallUsesNoHandles(node, TPrime, node);
+      _validateFfiLeafCallUsesNoHandles(node.argumentList.arguments, TPrime,
+          node);
     }
     _validateIsLeafIsConst(node);
   }
@@ -622,9 +637,8 @@
     }
   }
 
-  void _validateFfiLeafCallUsesNoHandles(
-      MethodInvocation node, DartType nativeType, AstNode errorNode) {
-    final args = node.argumentList.arguments;
+  void _validateFfiLeafCallUsesNoHandles(NodeList<Expression> args,
+      DartType nativeType, AstNode errorNode) {
     if (args.isNotEmpty) {
       for (final arg in args) {
         if (arg is NamedExpression) {
@@ -817,7 +831,8 @@
           FfiCode.MUST_BE_A_SUBTYPE, errorNode, [S, F, 'lookupFunction']);
     }
     _validateIsLeafIsConst(node);
-    _validateFfiLeafCallUsesNoHandles(node, S, typeArguments![0]);
+    _validateFfiLeafCallUsesNoHandles(node.argumentList.arguments, S,
+        typeArguments![0]);
   }
 
   /// Validate that none of the [annotations] are from `dart:ffi`.
diff --git a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
index e90a157..a11172c 100644
--- a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
@@ -26,4 +26,32 @@
       error(FfiCode.FFI_NATIVE_ONLY_STATIC, 31, 75),
     ]);
   }
+
+  test_FfiNativeCanUseHandles() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function(Handle)>('DoesntMatter')
+external Object doesntMatter(Object);
+''', []);
+  }
+
+  test_FfiNativeLeafMustNotReturnHandle() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function()>('DoesntMatter', isLeaf:true)
+external Object doesntMatter();
+''', [
+      error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 19, 90),
+    ]);
+  }
+
+  test_FfiNativeLeafMustNotTakeHandles() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Void Function(Handle)>('DoesntMatter', isLeaf:true)
+external void doesntMatter(Object o);
+''', [
+      error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 19, 100),
+    ]);
+  }
 }