| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 | 4 |
| 5 library analyzer.src.generated.type_system; | 5 library analyzer.src.generated.type_system; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:math' as math; | 8 import 'dart:math' as math; |
| 9 | 9 |
| 10 import 'package:analyzer/dart/ast/token.dart' show TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show TokenType; |
| 11 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/dart/element/type.dart'; | 12 import 'package:analyzer/dart/element/type.dart'; |
| 13 import 'package:analyzer/src/dart/element/element.dart'; | 13 import 'package:analyzer/src/dart/element/element.dart'; |
| 14 import 'package:analyzer/src/dart/element/type.dart'; | 14 import 'package:analyzer/src/dart/element/type.dart'; |
| 15 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 15 import 'package:analyzer/src/generated/engine.dart' |
| 16 show AnalysisContext, AnalysisOptionsImpl; |
| 16 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 17 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 17 import 'package:analyzer/src/generated/utilities_dart.dart'; | 18 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 18 | 19 |
| 19 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); | 20 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); |
| 20 | 21 |
| 21 /** | 22 /** |
| 22 * Implementation of [TypeSystem] using the strong mode rules. | 23 * Implementation of [TypeSystem] using the strong mode rules. |
| 23 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md | 24 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md |
| 24 */ | 25 */ |
| 25 class StrongTypeSystemImpl extends TypeSystem { | 26 class StrongTypeSystemImpl extends TypeSystem { |
| 27 /** |
| 28 * True if implicit casts should be allowed, otherwise false. |
| 29 * |
| 30 * This affects the behavior of [isAssignableTo]. |
| 31 */ |
| 32 final bool implicitCasts; |
| 33 |
| 34 StrongTypeSystemImpl({this.implicitCasts: true}); |
| 35 |
| 26 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { | 36 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
| 27 return ft.parameters.any((p) => predicate(p.type)); | 37 return ft.parameters.any((p) => predicate(p.type)); |
| 28 } | 38 } |
| 29 | 39 |
| 30 @override | 40 @override |
| 31 bool canPromoteToType(DartType to, DartType from) => isSubtypeOf(to, from); | 41 bool canPromoteToType(DartType to, DartType from) => isSubtypeOf(to, from); |
| 32 | 42 |
| 33 @override | 43 @override |
| 34 FunctionType functionTypeToConcreteType( | 44 FunctionType functionTypeToConcreteType( |
| 35 TypeProvider typeProvider, FunctionType t) { | 45 TypeProvider typeProvider, FunctionType t) { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 | 293 |
| 284 @override | 294 @override |
| 285 bool isAssignableTo(DartType fromType, DartType toType) { | 295 bool isAssignableTo(DartType fromType, DartType toType) { |
| 286 // TODO(leafp): Document the rules in play here | 296 // TODO(leafp): Document the rules in play here |
| 287 | 297 |
| 288 // An actual subtype | 298 // An actual subtype |
| 289 if (isSubtypeOf(fromType, toType)) { | 299 if (isSubtypeOf(fromType, toType)) { |
| 290 return true; | 300 return true; |
| 291 } | 301 } |
| 292 | 302 |
| 303 if (!implicitCasts) { |
| 304 return false; |
| 305 } |
| 306 |
| 293 // Don't allow implicit downcasts between function types | 307 // Don't allow implicit downcasts between function types |
| 294 // and call method objects, as these will almost always fail. | 308 // and call method objects, as these will almost always fail. |
| 295 if ((fromType is FunctionType && getCallMethodType(toType) != null) || | 309 if ((fromType is FunctionType && getCallMethodType(toType) != null) || |
| 296 (toType is FunctionType && getCallMethodType(fromType) != null)) { | 310 (toType is FunctionType && getCallMethodType(fromType) != null)) { |
| 297 return false; | 311 return false; |
| 298 } | 312 } |
| 299 | 313 |
| 300 // Don't allow a non-generic function where a generic one is expected. The | 314 // Don't allow a non-generic function where a generic one is expected. The |
| 301 // former wouldn't know how to handle type arguments being passed to it. | 315 // former wouldn't know how to handle type arguments being passed to it. |
| 302 // TODO(rnystrom): This same check also exists in FunctionTypeImpl.relate() | 316 // TODO(rnystrom): This same check also exists in FunctionTypeImpl.relate() |
| 303 // but we don't always reliably go through that code path. This should be | 317 // but we don't always reliably go through that code path. This should be |
| 304 // cleaned up to avoid the redundancy. | 318 // cleaned up to avoid the redundancy. |
| 305 if (fromType is FunctionType && | 319 if (fromType is FunctionType && |
| 306 toType is FunctionType && | 320 toType is FunctionType && |
| 307 fromType.typeFormals.isEmpty && | 321 fromType.typeFormals.isEmpty && |
| 308 toType.typeFormals.isNotEmpty) { | 322 toType.typeFormals.isNotEmpty) { |
| 309 return false; | 323 return false; |
| 310 } | 324 } |
| 311 | 325 |
| 312 // If the subtype relation goes the other way, allow the implicit downcast. | 326 // If the subtype relation goes the other way, allow the implicit |
| 313 // TODO(leafp): Emit warnings and hints for these in some way. | 327 // downcast. |
| 314 // TODO(leafp): Consider adding a flag to disable these? Or just rely on | |
| 315 // --warnings-as-errors? | |
| 316 if (isSubtypeOf(toType, fromType) || toType.isAssignableTo(fromType)) { | 328 if (isSubtypeOf(toType, fromType) || toType.isAssignableTo(fromType)) { |
| 317 // TODO(leafp): error if type is known to be exact (literal, | 329 // TODO(leafp,jmesserly): we emit warnings/hints for these in |
| 318 // instance creation). | 330 // src/task/strong/checker.dart, which is a bit inconsistent. That |
| 319 // TODO(leafp): Warn on composite downcast. | 331 // code should be handled into places that use isAssignableTo, such as |
| 320 // TODO(leafp): hint on object/dynamic downcast. | 332 // ErrorVerifier. |
| 321 // TODO(leafp): Consider allowing assignment casts. | |
| 322 return true; | 333 return true; |
| 323 } | 334 } |
| 324 | 335 |
| 325 return false; | 336 return false; |
| 326 } | 337 } |
| 327 | 338 |
| 328 bool isGroundType(DartType t) { | 339 bool isGroundType(DartType t) { |
| 329 // TODO(leafp): Revisit this. | 340 // TODO(leafp): Revisit this. |
| 330 if (t is TypeParameterType) { | 341 if (t is TypeParameterType) { |
| 331 return false; | 342 return false; |
| (...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 * [TypeParameterType], return their least upper bound in a type system | 1184 * [TypeParameterType], return their least upper bound in a type system |
| 1174 * specific manner. | 1185 * specific manner. |
| 1175 */ | 1186 */ |
| 1176 DartType _typeParameterLeastUpperBound( | 1187 DartType _typeParameterLeastUpperBound( |
| 1177 TypeProvider provider, DartType type1, DartType type2); | 1188 TypeProvider provider, DartType type1, DartType type2); |
| 1178 | 1189 |
| 1179 /** | 1190 /** |
| 1180 * Create either a strong mode or regular type system based on context. | 1191 * Create either a strong mode or regular type system based on context. |
| 1181 */ | 1192 */ |
| 1182 static TypeSystem create(AnalysisContext context) { | 1193 static TypeSystem create(AnalysisContext context) { |
| 1183 return (context.analysisOptions.strongMode) | 1194 var options = context.analysisOptions as AnalysisOptionsImpl; |
| 1184 ? new StrongTypeSystemImpl() | 1195 return options.strongMode |
| 1196 ? new StrongTypeSystemImpl(implicitCasts: options.implicitCasts) |
| 1185 : new TypeSystemImpl(); | 1197 : new TypeSystemImpl(); |
| 1186 } | 1198 } |
| 1187 } | 1199 } |
| 1188 | 1200 |
| 1189 /** | 1201 /** |
| 1190 * Implementation of [TypeSystem] using the rules in the Dart specification. | 1202 * Implementation of [TypeSystem] using the rules in the Dart specification. |
| 1191 */ | 1203 */ |
| 1192 class TypeSystemImpl extends TypeSystem { | 1204 class TypeSystemImpl extends TypeSystem { |
| 1193 TypeSystemImpl(); | 1205 TypeSystemImpl(); |
| 1194 | 1206 |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1478 } else { | 1490 } else { |
| 1479 passedOut = true; | 1491 passedOut = true; |
| 1480 } | 1492 } |
| 1481 } else if (type is FunctionType) { | 1493 } else if (type is FunctionType) { |
| 1482 _visitFunctionType(typeParam, type, paramIn); | 1494 _visitFunctionType(typeParam, type, paramIn); |
| 1483 } else if (type is InterfaceType) { | 1495 } else if (type is InterfaceType) { |
| 1484 _visitInterfaceType(typeParam, type, paramIn); | 1496 _visitInterfaceType(typeParam, type, paramIn); |
| 1485 } | 1497 } |
| 1486 } | 1498 } |
| 1487 } | 1499 } |
| OLD | NEW |