Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(630)

Unified Diff: pkg/kernel/lib/type_checker.dart

Issue 2619193003: Insert implicit downcasts in kernel strong mode. (Closed)
Patch Set: Merge Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/kernel/lib/transformations/insert_type_checks.dart ('k') | pkg/kernel/lib/type_environment.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/type_checker.dart
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index ab0351eb40b59ace8f18901b52027ecb27e0d356..45159b2d953bdb9330a6856470d6e1fadab948bd 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -85,6 +85,16 @@ abstract class TypeChecker {
/// [where] is an AST node indicating roughly where the check is required.
void checkAssignable(TreeNode where, DartType from, DartType to);
+ /// Checks that [expression], which has type [from], can be assigned to [to].
+ ///
+ /// Should return a downcast if necessary, or [expression] if no cast is
+ /// needed.
+ Expression checkAndDowncastExpression(
+ Expression expression, DartType from, DartType to) {
+ checkAssignable(expression, from, to);
+ return expression;
+ }
+
/// Indicates that type checking failed.
void fail(TreeNode where, String message);
}
@@ -108,8 +118,16 @@ class TypeCheckingVisitor
checker.checkAssignable(where, from, to);
}
- void checkAssignableExpression(Expression from, DartType to) {
- checker.checkAssignable(from, visitExpression(from), to);
+ Expression checkAndDowncastExpression(Expression from, DartType to) {
+ var parent = from.parent;
+ var type = visitExpression(from);
+ var result = checker.checkAndDowncastExpression(from, type, to);
+ result.parent = parent;
+ return result;
+ }
+
+ void checkExpressionNoDowncast(Expression expression, DartType to) {
+ checkAssignable(expression, visitExpression(expression), to);
}
void fail(TreeNode node, String message) {
@@ -146,7 +164,8 @@ class TypeCheckingVisitor
visitField(Field node) {
if (node.initializer != null) {
- checkAssignableExpression(node.initializer, node.type);
+ node.initializer =
+ checkAndDowncastExpression(node.initializer, node.type);
}
}
@@ -188,7 +207,8 @@ class TypeCheckingVisitor
void handleOptionalParameter(VariableDeclaration parameter) {
if (parameter.initializer != null) {
- checkAssignableExpression(parameter.initializer, parameter.type);
+ // Default parameter values cannot be downcast.
+ checkExpressionNoDowncast(parameter.initializer, parameter.type);
}
}
@@ -255,7 +275,8 @@ class TypeCheckingVisitor
var expectedType = substitution.substituteType(
function.positionalParameters[i].type,
contravariant: true);
- checkAssignableExpression(arguments.positional[i], expectedType);
+ arguments.positional[i] =
+ checkAndDowncastExpression(arguments.positional[i], expectedType);
}
for (int i = 0; i < arguments.named.length; ++i) {
var argument = arguments.named[i];
@@ -265,7 +286,8 @@ class TypeCheckingVisitor
var expectedType = substitution.substituteType(
function.namedParameters[j].type,
contravariant: true);
- checkAssignableExpression(argument.value, expectedType);
+ argument.value =
+ checkAndDowncastExpression(argument.value, expectedType);
found = true;
break;
}
@@ -344,9 +366,11 @@ class TypeCheckingVisitor
@override
DartType visitConditionalExpression(ConditionalExpression node) {
- checkAssignableExpression(node.condition, environment.boolType);
- checkAssignableExpression(node.then, node.staticType);
- checkAssignableExpression(node.otherwise, node.staticType);
+ node.condition =
+ checkAndDowncastExpression(node.condition, environment.boolType);
+ node.then = checkAndDowncastExpression(node.then, node.staticType);
+ node.otherwise =
+ checkAndDowncastExpression(node.otherwise, node.staticType);
return node.staticType;
}
@@ -419,24 +443,25 @@ class TypeCheckingVisitor
@override
DartType visitListLiteral(ListLiteral node) {
- for (var item in node.expressions) {
- checkAssignableExpression(item, node.typeArgument);
+ for (int i = 0; i < node.expressions.length; ++i) {
+ node.expressions[i] =
+ checkAndDowncastExpression(node.expressions[i], node.typeArgument);
}
return environment.literalListType(node.typeArgument);
}
@override
DartType visitLogicalExpression(LogicalExpression node) {
- checkAssignableExpression(node.left, environment.boolType);
- checkAssignableExpression(node.right, environment.boolType);
+ node.left = checkAndDowncastExpression(node.left, environment.boolType);
+ node.right = checkAndDowncastExpression(node.right, environment.boolType);
return environment.boolType;
}
@override
DartType visitMapLiteral(MapLiteral node) {
for (var entry in node.entries) {
- checkAssignableExpression(entry.key, node.keyType);
- checkAssignableExpression(entry.value, node.valueType);
+ entry.key = checkAndDowncastExpression(entry.key, node.keyType);
+ entry.value = checkAndDowncastExpression(entry.value, node.valueType);
}
return environment.literalMapType(node.keyType, node.valueType);
}
@@ -467,7 +492,8 @@ class TypeCheckingVisitor
var expectedType = instantiation.substituteType(
function.positionalParameters[i],
contravariant: true);
- checkAssignableExpression(arguments.positional[i], expectedType);
+ arguments.positional[i] =
+ checkAndDowncastExpression(arguments.positional[i], expectedType);
}
for (int i = 0; i < arguments.named.length; ++i) {
var argument = arguments.named[i];
@@ -477,7 +503,8 @@ class TypeCheckingVisitor
var expectedType = instantiation.substituteType(
function.namedParameters[j].type,
contravariant: true);
- checkAssignableExpression(argument.value, expectedType);
+ argument.value =
+ checkAndDowncastExpression(argument.value, expectedType);
found = true;
break;
}
@@ -674,7 +701,8 @@ class TypeCheckingVisitor
@override
visitDoStatement(DoStatement node) {
visitStatement(node.body);
- checkAssignableExpression(node.condition, environment.boolType);
+ node.condition =
+ checkAndDowncastExpression(node.condition, environment.boolType);
}
@override
@@ -700,23 +728,27 @@ class TypeCheckingVisitor
}
static final Name iteratorName = new Name('iterator');
- static final Name nextName = new Name('next');
+ static final Name currentName = new Name('current');
DartType getIterableElementType(DartType iterable) {
if (iterable is InterfaceType) {
var iteratorGetter =
hierarchy.getInterfaceMember(iterable.classNode, iteratorName);
if (iteratorGetter == null) return const DynamicType();
+ var castedIterable = hierarchy.getTypeAsInstanceOf(
+ iterable, iteratorGetter.enclosingClass);
var iteratorType = Substitution
- .fromInterfaceType(iterable)
+ .fromInterfaceType(castedIterable)
.substituteType(iteratorGetter.getterType);
if (iteratorType is InterfaceType) {
- var nextGetter =
- hierarchy.getInterfaceMember(iteratorType.classNode, nextName);
- if (nextGetter == null) return const DynamicType();
+ var currentGetter =
+ hierarchy.getInterfaceMember(iteratorType.classNode, currentName);
+ if (currentGetter == null) return const DynamicType();
+ var castedIteratorType = hierarchy.getTypeAsInstanceOf(
+ iteratorType, currentGetter.enclosingClass);
return Substitution
- .fromInterfaceType(iteratorType)
- .substituteType(nextGetter.getterType);
+ .fromInterfaceType(castedIteratorType)
+ .substituteType(currentGetter.getterType);
}
}
return const DynamicType();
@@ -736,7 +768,8 @@ class TypeCheckingVisitor
visitForStatement(ForStatement node) {
node.variables.forEach(visitVariableDeclaration);
if (node.condition != null) {
- checkAssignableExpression(node.condition, environment.boolType);
+ node.condition =
+ checkAndDowncastExpression(node.condition, environment.boolType);
}
node.updates.forEach(visitExpression);
visitStatement(node.body);
@@ -749,7 +782,8 @@ class TypeCheckingVisitor
@override
visitIfStatement(IfStatement node) {
- checkAssignableExpression(node.condition, environment.boolType);
+ node.condition =
+ checkAndDowncastExpression(node.condition, environment.boolType);
visitStatement(node.then);
if (node.otherwise != null) {
visitStatement(node.otherwise);
@@ -805,13 +839,15 @@ class TypeCheckingVisitor
@override
visitVariableDeclaration(VariableDeclaration node) {
if (node.initializer != null) {
- checkAssignableExpression(node.initializer, node.type);
+ node.initializer =
+ checkAndDowncastExpression(node.initializer, node.type);
}
}
@override
visitWhileStatement(WhileStatement node) {
- checkAssignableExpression(node.condition, environment.boolType);
+ node.condition =
+ checkAndDowncastExpression(node.condition, environment.boolType);
visitStatement(node.body);
}
@@ -832,13 +868,14 @@ class TypeCheckingVisitor
fail(node.expression, '$type is not an instance of $container');
}
} else {
- checkAssignableExpression(node.expression, environment.yieldType);
+ node.expression =
+ checkAndDowncastExpression(node.expression, environment.yieldType);
}
}
@override
visitFieldInitializer(FieldInitializer node) {
- checkAssignableExpression(node.value, node.field.type);
+ node.value = checkAndDowncastExpression(node.value, node.field.type);
}
@override
@@ -850,7 +887,8 @@ class TypeCheckingVisitor
@override
visitSuperInitializer(SuperInitializer node) {
handleCall(node.arguments, node.target.function,
- typeParameters: const <TypeParameter>[]);
+ typeParameters: const <TypeParameter>[],
+ receiver: getSuperReceiverType(node.target));
}
@override
« no previous file with comments | « pkg/kernel/lib/transformations/insert_type_checks.dart ('k') | pkg/kernel/lib/type_environment.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698