Skip to content

Commit

Permalink
Version 3.5.0-276.0.dev
Browse files Browse the repository at this point in the history
Merge 0c9067c into dev
  • Loading branch information
Dart CI committed Jun 18, 2024
2 parents 7245875 + 0c9067c commit 7f1642c
Show file tree
Hide file tree
Showing 26 changed files with 666 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1144,11 +1144,14 @@ class DeclarationHelper {
);
}
}
_addExtensionMembers(
type: element.thisType as InterfaceType,
excludedGetters: {},
includeMethods: true,
includeSetters: true);
var thisType = element.thisType;
if (thisType is InterfaceType) {
_addExtensionMembers(
type: thisType,
excludedGetters: {},
includeMethods: true,
includeSetters: true);
}
}

/// Completion is inside [declaration].
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../../../client/completion_driver_test.dart';

void main() {
defineReflectiveSuite(() {
defineReflectiveTests(FunctionInvocationTest);
});
}

@reflectiveTest
class FunctionInvocationTest extends AbstractCompletionDriverTest
with FunctionInvocationTestCases {}

mixin FunctionInvocationTestCases on AbstractCompletionDriverTest {
Future<void> test_implicitCall() async {
await computeSuggestions('''
extension E<T> on Comparator<T> {
Comparator<T> get inverse => (T a0, T b0) => this(^);
}
''');
// TODO(brianwilkerson): `super` should not be suggested here.
assertResponse(r'''
suggestions
a0
kind: parameter
b0
kind: parameter
true
kind: keyword
false
kind: keyword
null
kind: keyword
this
kind: keyword
const
kind: keyword
super
kind: keyword
switch
kind: keyword
''');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import 'for_element_test.dart' as for_element;
import 'for_statement_test.dart' as for_statement;
import 'function_declaration_test.dart' as function_declaration;
import 'function_expression_test.dart' as function_expression;
import 'function_invocation_test.dart' as function_invocation;
import 'if_element_test.dart' as if_element;
import 'if_statement_test.dart' as if_statement;
import 'implements_clause_test.dart' as implements_clause;
Expand Down Expand Up @@ -112,6 +113,7 @@ void main() {
for_statement.main();
function_declaration.main();
function_expression.main();
function_invocation.main();
if_element.main();
if_statement.main();
implements_clause.main();
Expand Down
4 changes: 2 additions & 2 deletions pkg/vm/lib/transformations/dynamic_interface_annotator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ InstanceConstant pragmaConstant(CoreTypes coreTypes, String pragmaName) {
});
}

void parseAndAnnotate(YamlList items, String pragmaName, Uri baseUri,
void parseAndAnnotate(YamlList? items, String pragmaName, Uri baseUri,
Component component, CoreTypes coreTypes, LibraryIndex libraryIndex,
{required bool allowMembers, bool onlyInstanceMembers = false}) {
if (items == null) return;
final pragma = pragmaConstant(coreTypes, pragmaName);

for (final item in items) {
final nodes = findNodes(item, baseUri, libraryIndex, component,
allowMembers: allowMembers, onlyInstanceMembers: onlyInstanceMembers);
Expand Down
16 changes: 15 additions & 1 deletion pkg/vm/lib/transformations/type_flow/analysis.dart
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,10 @@ final class _DispatchableInvocation extends _Invocation {
ConeType receiver,
Map<Member, _ReceiverTypeBuilder> targets,
TypeFlowAnalysis typeFlowAnalysis) {
if (kPrintTrace) {
tracePrint(
"Collecting targets for dynamically extendable receiver $receiver");
}
final cls = receiver.cls as _TFClassImpl;
// Collect possible targets among dynamically extendable
// subtypes as they may have allocated subtypes at run time.
Expand All @@ -770,6 +774,10 @@ final class _DispatchableInvocation extends _Invocation {
Member? target = extendableSubtype.getDispatchTarget(selector);
if (target != null) {
if (areArgumentsValidFor(target)) {
if (kPrintTrace) {
tracePrint(
"Found target $target in a dynamically extendable subtype $extendableSubtype");
}
// Overwrite previously added receiver type builder.
targets[target] = receiverTypeBuilder;
isDynamicallyOverridden = isDynamicallyOverridden ||
Expand All @@ -779,13 +787,19 @@ final class _DispatchableInvocation extends _Invocation {
assert(selector is DynamicSelector);
_recordMismatchedDynamicInvocation(target, typeFlowAnalysis);
}
} else {
isDynamicallyOverridden = true;
}
}
if (selector is DynamicSelector) {
targets[noSuchMethodMarker] = receiverTypeBuilder;
isDynamicallyOverridden = true;
}
return isDynamicallyOverridden && !selector.name.isPrivate;
if (kPrintTrace) {
tracePrint(
"isDynamicallyOverridden = $isDynamicallyOverridden, isPrivate = ${selector.name.isPrivate}");
}
return !isDynamicallyOverridden || selector.name.isPrivate;
}

void _recordMismatchedDynamicInvocation(
Expand Down
229 changes: 229 additions & 0 deletions runtime/tests/vm/dart/dynamic_module_pragmas_il_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Test for @pragma('dyn-module:extendable') and @pragma('dyn-module:can-be-overridden').

import 'package:vm/testing/il_matchers.dart';

@pragma('vm:never-inline')
void myprint(Object message) {
print(message);
}

abstract class A1 {
void foo();
void bar();
void baz();
}

class B1 extends A1 {
void foo() {
myprint('B1.foo');
}

void bar() {
myprint('B1.bar');
}

@pragma('vm:never-inline')
void baz() {
myprint('B1.baz');
}
}

class C1 extends B1 {
@pragma('vm:never-inline')
void baz() {
myprint('C1.baz');
}
}

@pragma('vm:never-inline')
@pragma('vm:testing:print-flow-graph')
void callA1(A1 obj) {
obj.foo();
obj.bar();
obj.baz();
}

@pragma('vm:never-inline')
@pragma('vm:testing:print-flow-graph')
void testIsA1(obj) {
myprint(obj is A1);
myprint(obj is B1);
myprint(obj is C1);
}

abstract class A2 {
void foo();
void bar();
void baz();
}

@pragma('dyn-module:extendable')
class B2 extends A2 {
void foo() {
myprint('B2.foo');
}

@pragma('dyn-module:can-be-overridden')
void bar() {
myprint('B2.bar');
}

@pragma('vm:never-inline')
void baz() {
myprint('B2.baz');
}
}

class C2 extends B2 {
@pragma('vm:never-inline')
void baz() {
myprint('C2.baz');
}
}

class D2 extends B2 {}

@pragma('vm:never-inline')
@pragma('vm:testing:print-flow-graph')
void callA2(A2 obj) {
obj.foo();
obj.bar();
obj.baz();
}

@pragma('vm:never-inline')
@pragma('vm:testing:print-flow-graph')
void testIsA2(obj) {
myprint(obj is A2);
myprint(obj is B2);
myprint(obj is C2);
}

List objs = [Object(), B1(), C1(), B2(), C2()];

main() {
for (final obj in objs) {
testIsA1(obj);
testIsA2(obj);
if (obj is A1) {
callA1(obj);
}
if (obj is A2) {
callA2(obj);
}
}
}

void matchIL$callA1(FlowGraph graph) {
graph.dump();
graph.match([
match.block('Graph', []),
match.block('Function', [
'obj' << match.Parameter(index: 0),
match.CheckStackOverflow(),
match.MoveArgument(match.any),
match.StaticCall(match.any),
match.MoveArgument(match.any),
match.StaticCall(match.any),
'cid' << match.LoadClassId('obj'),
match.MoveArgument('obj'),
match.DispatchTableCall('cid'),
match.DartReturn(match.any),
]),
]);
}

void matchIL$callA2(FlowGraph graph) {
graph.dump();
graph.match([
match.block('Graph', []),
match.block('Function', [
'obj' << match.Parameter(index: 0),
match.CheckStackOverflow(),
match.MoveArgument(match.any),
match.StaticCall(match.any),
'cid1' << match.LoadClassId('obj'),
match.Branch(match.TestRange('cid1'), ifTrue: 'B7', ifFalse: 'B8'),
]),
'B7' <<
match.block('Target', [
match.MoveArgument('obj'),
match.DispatchTableCall('cid1'),
match.Goto('B9'),
]),
'B8' <<
match.block('Target', [
match.MoveArgument('obj'),
match.InstanceCall('obj'),
match.Goto('B9'),
]),
'B9' <<
match.block('Join', [
'cid2' << match.LoadClassId('obj'),
match.Branch(match.TestRange('cid2'), ifTrue: 'B10', ifFalse: 'B11'),
]),
'B10' <<
match.block('Target', [
match.MoveArgument('obj'),
match.DispatchTableCall('cid2'),
match.Goto('B12'),
]),
'B11' <<
match.block('Target', [
match.MoveArgument('obj'),
match.InstanceCall('obj'),
match.Goto('B12'),
]),
'B12' <<
match.block('Join', [
match.DartReturn(match.any),
]),
]);
}

void matchIL$testIsA1(FlowGraph graph) {
graph.dump();
graph.match([
match.block('Graph', []),
match.block('Function', [
'obj' << match.Parameter(index: 0),
match.CheckStackOverflow(),
'cid' << match.LoadClassId('obj'),
'test1' << match.TestRange('cid'),
match.MoveArgument('test1'),
match.StaticCall('test1'),
match.MoveArgument('test1'),
match.StaticCall('test1'),
'test2' << match.EqualityCompare('cid', match.any, kind: '=='),
match.MoveArgument('test2'),
match.StaticCall('test2'),
match.DartReturn(match.any),
]),
]);
}

void matchIL$testIsA2(FlowGraph graph) {
graph.dump();
graph.match([
match.block('Graph', []),
match.block('Function', [
'obj' << match.Parameter(index: 0),
match.CheckStackOverflow(),
'test1' << match.InstanceOf('obj', match.any, match.any),
match.MoveArgument('test1'),
match.StaticCall('test1'),
'test2' << match.InstanceOf('obj', match.any, match.any),
match.MoveArgument('test2'),
match.StaticCall('test2'),
'cid' << match.LoadClassId('obj'),
'test3' << match.EqualityCompare('cid', match.any, kind: '=='),
match.MoveArgument('test3'),
match.StaticCall('test3'),
match.DartReturn(match.any),
]),
]);
}
Loading

0 comments on commit 7f1642c

Please sign in to comment.