[dart2js] new-rti: Generate correct $signature functions for closures

Change-Id: I0f75195be4a75b46793b1cd9ec49ecc6e783611d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109723
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams 2019-07-19 22:52:51 +00:00 committed by commit-bot@chromium.org
parent ebc180be95
commit 9cd47ac2e6
2 changed files with 71 additions and 1 deletions

View file

@ -514,7 +514,11 @@ class KernelSsaGraphBuilder extends ir.Visitor {
"Unexpected function signature: "
"$targetElement inside a non-closure: $target");
}
_buildMethodSignature(originalClosureNode);
if (options.experimentNewRti) {
_buildMethodSignatureNewRti(originalClosureNode);
} else {
_buildMethodSignature(originalClosureNode);
}
break;
case MemberKind.generatorBody:
_buildGeneratorBody(
@ -1233,6 +1237,21 @@ class KernelSsaGraphBuilder extends ir.Visitor {
_closeFunction();
}
/// Constructs a special signature function for a closure.
void _buildMethodSignatureNewRti(ir.FunctionNode originalClosureNode) {
// The signature function has no corresponding ir.Node, so we just use the
// targetElement to set up the type environment.
_openFunction(targetElement, checks: TargetChecks.none);
FunctionType functionType =
_elementMap.getFunctionType(originalClosureNode);
HInstruction rti =
_typeBuilder.analyzeTypeArgumentNewRti(functionType, sourceElement);
close(new HReturn(_abstractValueDomain, rti,
_sourceInformationBuilder.buildReturn(originalClosureNode)))
.addSuccessor(graph.exit);
_closeFunction();
}
/// Builds generative constructor body.
void _buildConstructorBody(ir.Constructor constructor) {
FunctionEntity constructorBody =

View file

@ -0,0 +1,51 @@
// Copyright (c) 2019, 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.
//
// dart2jsOptions=--experiment-new-rti
import "package:expect/expect.dart";
int fnInt2Int(int x) => x;
int fnIntOptInt2Int(int x, [int y = 0]) => x + y;
make1<A, B>(A a) {
return (B b) => a;
}
make2<A, B>(A a) {
A foo(B b) => a;
return foo;
}
class C<A> {
final A a;
C(this.a);
make<B>() => (B b) => a;
make2<B>() => (B b) => 'x';
}
main() {
Expect.isTrue(make1<int, int>(1) is int Function(int));
Expect.isTrue(make1<int, int>(1) is Object Function(int));
Expect.isTrue(make1<int, int>(1) is! String Function(int));
Expect.isTrue(make1<int, int>(1) is! int Function(String));
Expect.isTrue(make2<int, int>(1) is int Function(int));
Expect.isTrue(make2<int, int>(1) is Object Function(int));
Expect.isTrue(make2<int, int>(1) is! String Function(int));
Expect.isTrue(make2<int, int>(1) is! int Function(String));
Expect.isTrue(C<int>(1).make<String>() is int Function(String));
Expect.isTrue(C<int>(1).make<String>() is Object Function(String));
Expect.isTrue(C<int>(1).make<String>() is! String Function(int));
Expect.isTrue(C<int>(1).make2<int>() is String Function(int));
Expect.isTrue(C<int>(1).make2<int>() is Object Function(int));
Expect.isTrue(C<int>(1).make2<int>() is! int Function(String));
Expect.isTrue(C<int>(1).make2<int>() is! int Function(int));
Expect.isTrue(C<int>(1).make2<String>() is String Function(String));
Expect.isTrue(C<int>(1).make2<String>() is Object Function(String));
Expect.isTrue(C<int>(1).make2<String>() is! int Function(String));
Expect.isTrue(C<int>(1).make2<String>() is! String Function(int));
}