35ffad846d
Using Object causes issues in function types. This fixes an issue for running delta-blue in AOT strong mode. BUG= R=kmillikin@google.com Review URL: https://codereview.chromium.org/2492453002 .
148 lines
4.2 KiB
Dart
148 lines
4.2 KiB
Dart
// Copyright (c) 2016, 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.
|
|
library kernel.transformations.erasure;
|
|
|
|
import '../ast.dart';
|
|
import '../type_algebra.dart';
|
|
|
|
/// This pass is a temporary measure to run strong mode code in the VM, which
|
|
/// does not yet have the necessary runtime support.
|
|
///
|
|
/// Function type parameter lists are cleared and all uses of a function type
|
|
/// parameter are replaced by its upper bound.
|
|
///
|
|
/// All uses of type parameters in constants are replaced by 'dynamic'.
|
|
///
|
|
/// This does not preserve dynamic type safety.
|
|
class Erasure extends Transformer {
|
|
final Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
|
|
final Map<TypeParameter, DartType> constantSubstitution =
|
|
<TypeParameter, DartType>{};
|
|
|
|
int constantContexts = 0;
|
|
|
|
void transform(Program program) {
|
|
program.accept(this);
|
|
}
|
|
|
|
void pushConstantContext() {
|
|
++constantContexts;
|
|
}
|
|
|
|
void popConstantContext() {
|
|
--constantContexts;
|
|
}
|
|
|
|
bool get isInConstantContext => constantContexts > 0;
|
|
|
|
@override
|
|
visitDartType(DartType type) {
|
|
type = substitute(type, substitution);
|
|
if (isInConstantContext) {
|
|
type = substitute(type, constantSubstitution);
|
|
}
|
|
return type;
|
|
}
|
|
|
|
@override
|
|
visitClass(Class node) {
|
|
for (var parameter in node.typeParameters) {
|
|
constantSubstitution[parameter] = const DynamicType();
|
|
}
|
|
node.transformChildren(this);
|
|
constantSubstitution.clear();
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitProcedure(Procedure node) {
|
|
if (node.kind == ProcedureKind.Factory) {
|
|
assert(node.enclosingClass != null);
|
|
assert(node.enclosingClass.typeParameters.length ==
|
|
node.function.typeParameters.length);
|
|
// Factories can have function type parameters as long as they correspond
|
|
// exactly to those on the enclosing class. However, these type parameters
|
|
// may still not be in a constant.
|
|
for (var parameter in node.function.typeParameters) {
|
|
constantSubstitution[parameter] = const DynamicType();
|
|
}
|
|
// Skip the visitFunctionNode but traverse body.
|
|
node.function.transformChildren(this);
|
|
node.function.typeParameters.forEach(constantSubstitution.remove);
|
|
} else {
|
|
node.transformChildren(this);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
bool isObject(DartType type) {
|
|
return type is InterfaceType && type.classNode.supertype == null;
|
|
}
|
|
|
|
@override
|
|
visitFunctionNode(FunctionNode node) {
|
|
for (var parameter in node.typeParameters) {
|
|
substitution[parameter] = const DynamicType();
|
|
}
|
|
for (var parameter in node.typeParameters) {
|
|
if (!isObject(parameter.bound)) {
|
|
substitution[parameter] = substitute(parameter.bound, substitution);
|
|
}
|
|
}
|
|
node.transformChildren(this);
|
|
node.typeParameters.forEach(substitution.remove);
|
|
node.typeParameters.clear();
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitStaticInvocation(StaticInvocation node) {
|
|
if (node.target.kind != ProcedureKind.Factory) {
|
|
node.arguments.types.clear();
|
|
}
|
|
if (node.isConst) pushConstantContext();
|
|
node.transformChildren(this);
|
|
if (node.isConst) popConstantContext();
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitMethodInvocation(MethodInvocation node) {
|
|
node.arguments.types.clear();
|
|
node.transformChildren(this);
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitDirectMethodInvocation(DirectMethodInvocation node) {
|
|
node.arguments.types.clear();
|
|
node.transformChildren(this);
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitConstructorInvocation(ConstructorInvocation node) {
|
|
if (node.isConst) pushConstantContext();
|
|
node.transformChildren(this);
|
|
if (node.isConst) popConstantContext();
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitListLiteral(ListLiteral node) {
|
|
if (node.isConst) pushConstantContext();
|
|
node.transformChildren(this);
|
|
if (node.isConst) popConstantContext();
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
visitMapLiteral(MapLiteral node) {
|
|
if (node.isConst) pushConstantContext();
|
|
node.transformChildren(this);
|
|
if (node.isConst) popConstantContext();
|
|
return node;
|
|
}
|
|
}
|