Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit e141400

Browse files
author
Dart CI
committed
Version 2.14.0-339.0.dev
Merge commit '93d5c4eeeff269d798fe66df78aafc28ed3ab605' into 'dev'
2 parents d65b397 + 93d5c4e commit e141400

24 files changed

+1371
-23
lines changed

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,12 +277,26 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
277277

278278
for (Annotation annotation in annotations) {
279279
if (annotation.name.name == _ffiNativeName) {
280+
// All FFI Natives must be static.
280281
final isStatic = (node is FunctionDeclaration) ||
281282
((node is MethodDeclaration) && node.isStatic);
282283
if (!isStatic) {
283284
_errorReporter.reportErrorForNode(
284285
FfiCode.FFI_NATIVE_ONLY_STATIC, node);
285286
}
287+
// Leaf call FFI Natives can't use Handles.
288+
ArgumentList? argumentList = annotation.arguments;
289+
if (argumentList != null) {
290+
NodeList<Expression> arguments = argumentList.arguments;
291+
TypeArgumentList? typeArgumentList = annotation.typeArguments;
292+
if (typeArgumentList != null) {
293+
NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
294+
if (typeArguments.isNotEmpty && typeArguments[0].type != null) {
295+
_validateFfiLeafCallUsesNoHandles(
296+
arguments, typeArguments[0].type!, node);
297+
}
298+
}
299+
}
286300
}
287301
}
288302
}
@@ -530,7 +544,8 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
530544
_errorReporter.reportErrorForNode(
531545
FfiCode.MUST_BE_A_SUBTYPE, node, [TPrime, F, 'asFunction']);
532546
}
533-
_validateFfiLeafCallUsesNoHandles(node, TPrime, node);
547+
_validateFfiLeafCallUsesNoHandles(node.argumentList.arguments, TPrime,
548+
node);
534549
}
535550
_validateIsLeafIsConst(node);
536551
}
@@ -622,9 +637,8 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
622637
}
623638
}
624639

625-
void _validateFfiLeafCallUsesNoHandles(
626-
MethodInvocation node, DartType nativeType, AstNode errorNode) {
627-
final args = node.argumentList.arguments;
640+
void _validateFfiLeafCallUsesNoHandles(NodeList<Expression> args,
641+
DartType nativeType, AstNode errorNode) {
628642
if (args.isNotEmpty) {
629643
for (final arg in args) {
630644
if (arg is NamedExpression) {
@@ -817,7 +831,8 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
817831
FfiCode.MUST_BE_A_SUBTYPE, errorNode, [S, F, 'lookupFunction']);
818832
}
819833
_validateIsLeafIsConst(node);
820-
_validateFfiLeafCallUsesNoHandles(node, S, typeArguments![0]);
834+
_validateFfiLeafCallUsesNoHandles(node.argumentList.arguments, S,
835+
typeArguments![0]);
821836
}
822837

823838
/// Validate that none of the [annotations] are from `dart:ffi`.

pkg/analyzer/test/src/diagnostics/ffi_native_test.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,32 @@ class K {
2626
error(FfiCode.FFI_NATIVE_ONLY_STATIC, 31, 75),
2727
]);
2828
}
29+
30+
test_FfiNativeCanUseHandles() async {
31+
await assertErrorsInCode(r'''
32+
import 'dart:ffi';
33+
@FfiNative<Handle Function(Handle)>('DoesntMatter')
34+
external Object doesntMatter(Object);
35+
''', []);
36+
}
37+
38+
test_FfiNativeLeafMustNotReturnHandle() async {
39+
await assertErrorsInCode(r'''
40+
import 'dart:ffi';
41+
@FfiNative<Handle Function()>('DoesntMatter', isLeaf:true)
42+
external Object doesntMatter();
43+
''', [
44+
error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 19, 90),
45+
]);
46+
}
47+
48+
test_FfiNativeLeafMustNotTakeHandles() async {
49+
await assertErrorsInCode(r'''
50+
import 'dart:ffi';
51+
@FfiNative<Void Function(Handle)>('DoesntMatter', isLeaf:true)
52+
external void doesntMatter(Object o);
53+
''', [
54+
error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 19, 100),
55+
]);
56+
}
2957
}

pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,12 @@ class ConstantsTransformer extends RemovingTransformer {
707707
return evaluateAndTransformWithContext(node, node);
708708
}
709709

710+
@override
711+
TreeNode visitRedirectingFactoryTearOff(
712+
RedirectingFactoryTearOff node, TreeNode? removalSentinel) {
713+
return evaluateAndTransformWithContext(node, node);
714+
}
715+
710716
@override
711717
TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
712718
Instantiation result =
@@ -3434,7 +3440,7 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
34343440

34353441
@override
34363442
Constant visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
3437-
return defaultExpression(node);
3443+
return canonicalize(new RedirectingFactoryTearOffConstant(node.target));
34383444
}
34393445

34403446
@override

pkg/front_end/lib/src/fasta/kernel/expression_generator.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3178,8 +3178,13 @@ class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
31783178
tearOffExpression = _helper.forest
31793179
.createConstructorTearOff(token.charOffset, tearOff);
31803180
} else if (tearOff is Procedure) {
3181-
tearOffExpression =
3182-
_helper.forest.createStaticTearOff(token.charOffset, tearOff);
3181+
if (tearOff.isRedirectingFactory) {
3182+
tearOffExpression = _helper.forest
3183+
.createRedirectingFactoryTearOff(token.charOffset, tearOff);
3184+
} else {
3185+
tearOffExpression = _helper.forest
3186+
.createStaticTearOff(token.charOffset, tearOff);
3187+
}
31833188
} else if (tearOff != null) {
31843189
unhandled("${tearOff.runtimeType}", "buildPropertyAccess",
31853190
operatorOffset, _helper.uri);

pkg/front_end/lib/src/fasta/kernel/forest.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,9 +836,17 @@ class Forest {
836836
StaticTearOff createStaticTearOff(int fileOffset, Procedure procedure) {
837837
// ignore: unnecessary_null_comparison
838838
assert(fileOffset != null);
839+
assert(!procedure.isRedirectingFactory);
839840
return new StaticTearOff(procedure)..fileOffset = fileOffset;
840841
}
841842

843+
RedirectingFactoryTearOff createRedirectingFactoryTearOff(
844+
int fileOffset, Procedure procedure) {
845+
// ignore: unnecessary_null_comparison
846+
assert(fileOffset != null);
847+
return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
848+
}
849+
842850
Instantiation createInstantiation(
843851
int fileOffset, Expression expression, List<DartType> typeArguments) {
844852
// ignore: unnecessary_null_comparison

pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ class InferenceVisitor
225225
@override
226226
ExpressionInferenceResult visitRedirectingFactoryTearOff(
227227
RedirectingFactoryTearOff node, DartType typeContext) {
228-
return _unhandledExpression(node, typeContext);
228+
DartType type =
229+
node.target.function.computeFunctionType(inferrer.library.nonNullable);
230+
return inferrer.instantiateTearOff(type, typeContext, node);
229231
}
230232

231233
@override

pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static method main() → dynamic
6262
return self::test();
6363

6464
constants {
65-
#C1 = static-tearoff self::A::redirectingFactory
66-
#C2 = static-tearoff self::A::redirectingFactoryChild
67-
#C3 = static-tearoff self::A::redirectingTwice
65+
#C1 = redirecting-factory-tearoff self::A::redirectingFactory
66+
#C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
67+
#C3 = redirecting-factory-tearoff self::A::redirectingTwice
6868
}

pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static method main() → dynamic
6262
return self::test();
6363

6464
constants {
65-
#C1 = static-tearoff self::A::redirectingFactory
66-
#C2 = static-tearoff self::A::redirectingFactoryChild
67-
#C3 = static-tearoff self::A::redirectingTwice
65+
#C1 = redirecting-factory-tearoff self::A::redirectingFactory
66+
#C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
67+
#C3 = redirecting-factory-tearoff self::A::redirectingTwice
6868
}

pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static method main() → dynamic
6262
return self::test();
6363

6464
constants {
65-
#C1 = static-tearoff self::A::redirectingFactory
66-
#C2 = static-tearoff self::A::redirectingFactoryChild
67-
#C3 = static-tearoff self::A::redirectingTwice
65+
#C1 = redirecting-factory-tearoff self::A::redirectingFactory
66+
#C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
67+
#C3 = redirecting-factory-tearoff self::A::redirectingTwice
6868
}

pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static method main() → dynamic
6262
return self::test();
6363

6464
constants {
65-
#C1 = static-tearoff self::A::redirectingFactory
66-
#C2 = static-tearoff self::A::redirectingFactoryChild
67-
#C3 = static-tearoff self::A::redirectingTwice
65+
#C1 = redirecting-factory-tearoff self::A::redirectingFactory
66+
#C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
67+
#C3 = redirecting-factory-tearoff self::A::redirectingTwice
6868
}

0 commit comments

Comments
 (0)