| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library kernel.transformations.insert_covariance_checks; | 4 library kernel.transformations.insert_covariance_checks; |
| 5 | 5 |
| 6 import '../class_hierarchy.dart'; | 6 import '../class_hierarchy.dart'; |
| 7 import '../clone.dart'; | 7 import '../clone.dart'; |
| 8 import '../core_types.dart'; | 8 import '../core_types.dart'; |
| 9 import '../kernel.dart'; | 9 import '../kernel.dart'; |
| 10 import '../log.dart'; | 10 import '../log.dart'; |
| 11 import '../type_algebra.dart'; | 11 import '../type_algebra.dart'; |
| 12 import '../type_environment.dart'; | 12 import '../type_environment.dart'; |
| 13 | 13 |
| 14 // TODO: Should helper be removed? | |
| 15 DartType substituteBounds(DartType type, Map<TypeParameter, DartType> upper, | 14 DartType substituteBounds(DartType type, Map<TypeParameter, DartType> upper, |
| 16 Map<TypeParameter, DartType> lower) { | 15 Map<TypeParameter, DartType> lower) { |
| 17 return Substitution | 16 return Substitution |
| 18 .fromUpperAndLowerBounds(upper, lower) | 17 .fromUpperAndLowerBounds(upper, lower) |
| 19 .substituteType(type); | 18 .substituteType(type); |
| 20 } | 19 } |
| 21 | 20 |
| 22 /// Inserts checked entry points for methods in order to enforce type safety | 21 /// Inserts checked entry points for methods in order to enforce type safety |
| 23 /// in face on covariant subtyping. | 22 /// in face on covariant subtyping. |
| 24 /// | 23 /// |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 // | 109 // |
| 111 // The "substitution" maps translate type parameters to their exact type, | 110 // The "substitution" maps translate type parameters to their exact type, |
| 112 // while the "upper bound" maps translate type parameters to their erased | 111 // while the "upper bound" maps translate type parameters to their erased |
| 113 // upper bounds. | 112 // upper bounds. |
| 114 Map<TypeParameter, DartType> ownSubstitution; | 113 Map<TypeParameter, DartType> ownSubstitution; |
| 115 Map<TypeParameter, DartType> ownUpperBounds; | 114 Map<TypeParameter, DartType> ownUpperBounds; |
| 116 Map<TypeParameter, DartType> superSubstitution; | 115 Map<TypeParameter, DartType> superSubstitution; |
| 117 Map<TypeParameter, DartType> superUpperBounds; | 116 Map<TypeParameter, DartType> superUpperBounds; |
| 118 | 117 |
| 119 /// Members for which a checked entry point must be created in this current | 118 /// Members for which a checked entry point must be created in this current |
| 120 /// class. | 119 /// class, indexed by name. |
| 121 Set<Member> membersNeedingCheckedEntryPoint = new Set<Member>(); | 120 Map<Name, Member> membersNeedingCheckedEntryPoint = <Name, Member>{}; |
| 122 | 121 |
| 123 _ClassTransformer(this.host, InsertCovarianceChecks global) | 122 _ClassTransformer(this.host, InsertCovarianceChecks global) |
| 124 : hierarchy = global.hierarchy, | 123 : hierarchy = global.hierarchy, |
| 125 types = global.types, | 124 types = global.types, |
| 126 this.global = global; | 125 this.global = global; |
| 127 | 126 |
| 128 /// Mark [parameter] unsafe, with [type] as a potential argument type. | 127 /// Mark [parameter] unsafe, with [type] as a potential argument type. |
| 129 void addUnsafeParameter( | 128 void addUnsafeParameter( |
| 130 VariableDeclaration parameter, DartType type, Member member) { | 129 VariableDeclaration parameter, DartType type, Member member) { |
| 131 unsafeParameterTypes.putIfAbsent(parameter, () => <DartType>[]).add(type); | 130 unsafeParameterTypes.putIfAbsent(parameter, () => <DartType>[]).add(type); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 151 bool hasCheckedEntryPoint(Member member, {bool setter: false}) { | 150 bool hasCheckedEntryPoint(Member member, {bool setter: false}) { |
| 152 if (!setter && member is Field) { | 151 if (!setter && member is Field) { |
| 153 return false; // Field getters never have checked entry points. | 152 return false; // Field getters never have checked entry points. |
| 154 } | 153 } |
| 155 return global.membersWithCheckedEntryPoint.contains(member); | 154 return global.membersWithCheckedEntryPoint.contains(member); |
| 156 } | 155 } |
| 157 | 156 |
| 158 /// Ensures that a checked entry point for [member] will be emitted in the | 157 /// Ensures that a checked entry point for [member] will be emitted in the |
| 159 /// current class. | 158 /// current class. |
| 160 void requireLocalCheckedEntryPoint(Member member) { | 159 void requireLocalCheckedEntryPoint(Member member) { |
| 161 if (membersNeedingCheckedEntryPoint.add(member)) { | 160 membersNeedingCheckedEntryPoint[member.name] = member; |
| 162 global.membersWithCheckedEntryPoint.add(member); | 161 global.membersWithCheckedEntryPoint.add(member); |
| 163 } | |
| 164 } | 162 } |
| 165 | 163 |
| 166 void transformClass() { | 164 void transformClass() { |
| 167 if (host.isMixinApplication) { | 165 if (host.isMixinApplication) { |
| 168 // TODO(asgerf): We need a way to support mixin applications with unsafe | 166 // TODO(asgerf): We need a way to support mixin applications with unsafe |
| 169 // overrides. This version assumes mixins have been resolved by cloning. | 167 // overrides. This version assumes mixins have been resolved by cloning. |
| 170 // We could generate a subclass of the mixin application containing the | 168 // We could generate a subclass of the mixin application containing the |
| 171 // checked entry points. | 169 // checked entry points. |
| 172 throw 'Mixin applications must be resolved before inserting covariance ' | 170 throw 'Mixin applications must be resolved before inserting covariance ' |
| 173 'checks'; | 171 'checks'; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 if (superMember is Procedure) { | 216 if (superMember is Procedure) { |
| 219 checkProcedureOverride(ownMember, superMember); | 217 checkProcedureOverride(ownMember, superMember); |
| 220 } else if (superMember is Field && isSetter) { | 218 } else if (superMember is Field && isSetter) { |
| 221 checkSetterFieldOverride(ownMember, superMember); | 219 checkSetterFieldOverride(ownMember, superMember); |
| 222 } | 220 } |
| 223 } else if (isSetter) { | 221 } else if (isSetter) { |
| 224 checkFieldOverride(ownMember, superMember); | 222 checkFieldOverride(ownMember, superMember); |
| 225 } | 223 } |
| 226 }); | 224 }); |
| 227 | 225 |
| 228 for (Member member in membersNeedingCheckedEntryPoint) { | 226 for (Member member in membersNeedingCheckedEntryPoint.values) { |
| 229 ownSubstitution = getSubstitutionMap( | 227 ownSubstitution = getSubstitutionMap( |
| 230 hierarchy.getClassAsInstanceOf(host, member.enclosingClass)); | 228 hierarchy.getClassAsInstanceOf(host, member.enclosingClass)); |
| 231 ownSubstitution = ensureMutable(ownSubstitution); | 229 ownSubstitution = ensureMutable(ownSubstitution); |
| 232 generateCheckedEntryPoint(member); | 230 generateCheckedEntryPoint(member); |
| 233 } | 231 } |
| 234 } | 232 } |
| 235 | 233 |
| 236 /// Compute an upper bound of the types in [inputTypes]. | 234 /// Compute an upper bound of the types in [inputTypes]. |
| 237 /// | 235 /// |
| 238 /// We use this to compute a trustworthy type for a parameter, given a list | 236 /// We use this to compute a trustworthy type for a parameter, given a list |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 @override | 513 @override |
| 516 visitPropertySet(PropertySet node) { | 514 visitPropertySet(PropertySet node) { |
| 517 var target = getChecked(node.receiver, node.interfaceTarget); | 515 var target = getChecked(node.receiver, node.interfaceTarget); |
| 518 if (target != null) { | 516 if (target != null) { |
| 519 node.interfaceTarget = target; | 517 node.interfaceTarget = target; |
| 520 node.name = target.name; | 518 node.name = target.name; |
| 521 } | 519 } |
| 522 node.visitChildren(this); | 520 node.visitChildren(this); |
| 523 } | 521 } |
| 524 } | 522 } |
| OLD | NEW |