Index: pkg/kernel/lib/transformations/insert_type_checks.dart |
diff --git a/pkg/kernel/lib/transformations/insert_type_checks.dart b/pkg/kernel/lib/transformations/insert_type_checks.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..01db445a5e6a2056c54326b9046826a6a07fed93 |
--- /dev/null |
+++ b/pkg/kernel/lib/transformations/insert_type_checks.dart |
@@ -0,0 +1,58 @@ |
+// 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.insert_type_checks; |
+ |
+import '../ast.dart'; |
+import '../class_hierarchy.dart'; |
+import '../core_types.dart'; |
+import '../log.dart'; |
+import '../type_checker.dart'; |
+ |
+/// Inserts implicit downcasts in method bodies to ensure type safety. |
+/// |
+/// This does not deal with covariant override and covariant use of type |
+/// parameters. |
+/// |
+/// Ideally this should be done when initially generating kernel IR, but this |
+/// is not practical at the moment. |
+class InsertTypeChecks { |
+ CoreTypes coreTypes; |
+ ClassHierarchy hierarchy; |
+ |
+ InsertTypeChecks({this.coreTypes, this.hierarchy}); |
+ |
+ void transformProgram(Program program) { |
+ coreTypes ??= new CoreTypes(program); |
+ hierarchy ??= new ClassHierarchy(program); |
+ new CheckInsertingTypeChecker(coreTypes, hierarchy).checkProgram(program); |
+ } |
+} |
+ |
+class CheckInsertingTypeChecker extends TypeChecker { |
+ CheckInsertingTypeChecker(CoreTypes coreTypes, ClassHierarchy hierarchy) |
+ : super(coreTypes, hierarchy); |
+ |
+ @override |
+ void fail(TreeNode where, String message) { |
+ log.severe('${where.location}: $message'); |
+ } |
+ |
+ @override |
+ void checkAssignable(TreeNode where, DartType from, DartType to) { |
+ if (!environment.isSubtypeOf(from, to)) { |
+ fail(where, '$from cannot be assigned to $to'); |
+ } |
+ } |
+ |
+ @override |
+ Expression checkAndDowncastExpression( |
+ Expression expression, DartType from, DartType to) { |
+ if (!environment.isSubtypeOf(from, to)) { |
+ return new AsExpression(expression, to) |
+ ..fileOffset = expression.fileOffset; |
+ } else { |
+ return expression; |
+ } |
+ } |
+} |