| // 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; |
| } |
| } |
| } |