[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 <joshualitt@google.com>
This commit is contained in:
Aske Simon Christensen 2022-12-08 13:54:57 +00:00
parent ad06d73ace
commit 8c717be409
3 changed files with 39 additions and 6 deletions

View file

@ -197,8 +197,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
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<w.ValueType, w.ValueType>
// 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);
}

View file

@ -521,8 +521,8 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
@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<ConstantInfo?> {
.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)

View file

@ -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