From 8c717be409788886ee15fb7ae4f74b07804aca1e Mon Sep 17 00:00:00 2001 From: Aske Simon Christensen Date: Thu, 8 Dec 2022 13:54:57 +0000 Subject: [PATCH] [dart2wasm] Emit correct runtime type for tear-offs The static type of a tear-off is the signature type of the method. The runtime type is the same with the types of all covariant parameters replaced by `Object?`. Change-Id: I9bb36a36ec04e27deab2b31c977fadac515ad561 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273845 Reviewed-by: Joshua Litt --- pkg/dart2wasm/lib/code_generator.dart | 5 ++-- pkg/dart2wasm/lib/constants.dart | 6 ++--- pkg/dart2wasm/lib/translator.dart | 34 +++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart index b8a186ed273..55db2d73030 100644 --- a/pkg/dart2wasm/lib/code_generator.dart +++ b/pkg/dart2wasm/lib/code_generator.dart @@ -197,8 +197,7 @@ class CodeGenerator extends ExpressionVisitor1 void generateTearOffGetter(Procedure procedure) { _initializeThis(member); - DartType functionType = - procedure.function.computeFunctionType(Nullability.nonNullable); + DartType functionType = translator.getTearOffType(procedure); ClosureImplementation closure = translator.getTearOffClosure(procedure); w.StructType struct = closure.representation.closureStruct; @@ -1842,7 +1841,7 @@ class CodeGenerator extends ExpressionVisitor1 // Super tear-off w.StructType closureStruct = _pushClosure( translator.getTearOffClosure(target), - target.function.computeFunctionType(Nullability.nonNullable), + translator.getTearOffType(target), () => visitThis(w.RefType.data(nullable: false))); return w.RefType.def(closureStruct, nullable: false); } diff --git a/pkg/dart2wasm/lib/constants.dart b/pkg/dart2wasm/lib/constants.dart index 8725a10631c..108d18536a8 100644 --- a/pkg/dart2wasm/lib/constants.dart +++ b/pkg/dart2wasm/lib/constants.dart @@ -521,8 +521,8 @@ class ConstantCreator extends ConstantVisitor { @override ConstantInfo? visitStaticTearOffConstant(StaticTearOffConstant constant) { Procedure member = constant.targetReference.asProcedure; - Constant functionTypeConstant = TypeLiteralConstant( - member.function.computeFunctionType(Nullability.nonNullable)); + Constant functionTypeConstant = + TypeLiteralConstant(translator.getTearOffType(member)); ensureConstant(functionTypeConstant); ClosureImplementation closure = translator.getTearOffClosure(member); w.StructType struct = closure.representation.closureStruct; @@ -550,7 +550,7 @@ class ConstantCreator extends ConstantVisitor { .toList(); Procedure tearOffProcedure = tearOffConstant.targetReference.asProcedure; FunctionType tearOffFunctionType = - tearOffProcedure.function.computeFunctionType(Nullability.nonNullable); + translator.getTearOffType(tearOffProcedure); FunctionType instantiatedFunctionType = Substitution.fromPairs( tearOffFunctionType.typeParameters, constant.types) .substituteType(tearOffFunctionType.withoutTypeParameters) diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart index 3de6c9abeb7..0a580ef1bc5 100644 --- a/pkg/dart2wasm/lib/translator.dart +++ b/pkg/dart2wasm/lib/translator.dart @@ -330,6 +330,40 @@ class Translator with KernelNodes { : coreTypes.objectClass; } + /// Compute the runtime type of a tear-off. This is the signature of the + /// method with the types of all covariant parameters replaced by `Object?`. + FunctionType getTearOffType(Procedure method) { + assert(method.kind == ProcedureKind.Method); + final FunctionType staticType = method.getterType as FunctionType; + + final positionalParameters = List.of(staticType.positionalParameters); + assert(positionalParameters.length == + method.function.positionalParameters.length); + for (int i = 0; i < positionalParameters.length; i++) { + final param = method.function.positionalParameters[i]; + if (param.isCovariantByDeclaration || param.isCovariantByClass) { + positionalParameters[i] = coreTypes.objectNullableRawType; + } + } + + final namedParameters = List.of(staticType.namedParameters); + assert(namedParameters.length == method.function.namedParameters.length); + for (int i = 0; i < namedParameters.length; i++) { + final param = method.function.namedParameters[i]; + if (param.isCovariantByDeclaration || param.isCovariantByClass) { + namedParameters[i] = NamedType( + namedParameters[i].name, coreTypes.objectNullableRawType, + isRequired: namedParameters[i].isRequired); + } + } + + return FunctionType( + positionalParameters, staticType.returnType, Nullability.nonNullable, + namedParameters: namedParameters, + typeParameters: staticType.typeParameters, + requiredParameterCount: staticType.requiredParameterCount); + } + /// Creates a [Tag] for a void [FunctionType] with two parameters, /// a [topInfo.nonNullableType] parameter to hold an exception, and a /// [stackTraceInfo.nonNullableType] to hold a stack trace. This single