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 |