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 dev_compiler.src.checker.rules; | 5 library dev_compiler.src.checker.rules; |
6 | 6 |
7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
8 import 'package:analyzer/src/generated/element.dart'; | 8 import 'package:analyzer/src/generated/element.dart'; |
9 import 'package:analyzer/src/generated/resolver.dart'; | 9 import 'package:analyzer/src/generated/resolver.dart'; |
10 | 10 |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 } | 257 } |
258 | 258 |
259 if (t is InterfaceType) { | 259 if (t is InterfaceType) { |
260 var typeArguments = t.typeArguments; | 260 var typeArguments = t.typeArguments; |
261 for (var typeArgument in typeArguments) { | 261 for (var typeArgument in typeArguments) { |
262 if (!_isTop(typeArgument)) return false; | 262 if (!_isTop(typeArgument)) return false; |
263 } | 263 } |
264 return true; | 264 return true; |
265 } | 265 } |
266 | 266 |
267 throw new StateError("Unexpected type"); | 267 // We should not see any other type aside from malformed code. |
| 268 return false; |
268 } | 269 } |
269 | 270 |
270 /// Check that f1 is a subtype of f2. [ignoreReturn] is used in the DDC | 271 /// Check that f1 is a subtype of f2. [ignoreReturn] is used in the DDC |
271 /// checker to determine whether f1 would be a subtype of f2 if the return | 272 /// checker to determine whether f1 would be a subtype of f2 if the return |
272 /// type of f1 is set to match f2's return type. | 273 /// type of f1 is set to match f2's return type. |
273 // [fuzzyArrows] indicates whether or not the f1 and f2 should be | 274 // [fuzzyArrows] indicates whether or not the f1 and f2 should be |
274 // treated as fuzzy arrow types (and hence dynamic parameters to f2 treated as | 275 // treated as fuzzy arrow types (and hence dynamic parameters to f2 treated as |
275 // bottom). | 276 // bottom). |
276 bool isFunctionSubTypeOf(FunctionType f1, FunctionType f2, | 277 bool isFunctionSubTypeOf(FunctionType f1, FunctionType f2, |
277 {bool fuzzyArrows: true, bool ignoreReturn: false}) { | 278 {bool fuzzyArrows: true, bool ignoreReturn: false}) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 // T is not dynamic or object (handled above) | 401 // T is not dynamic or object (handled above) |
401 // S != T (handled above) | 402 // S != T (handled above) |
402 // So only true if bound of S is S' and | 403 // So only true if bound of S is S' and |
403 // S' <: T | 404 // S' <: T |
404 if (t1 is TypeParameterType) { | 405 if (t1 is TypeParameterType) { |
405 DartType bound = t1.element.bound; | 406 DartType bound = t1.element.bound; |
406 if (bound == null) return false; | 407 if (bound == null) return false; |
407 return isSubTypeOf(bound, t2); | 408 return isSubTypeOf(bound, t2); |
408 } | 409 } |
409 | 410 |
| 411 if (t2 is TypeParameterType) { |
| 412 return false; |
| 413 } |
| 414 |
410 if (t2.isDartCoreFunction) { | 415 if (t2.isDartCoreFunction) { |
411 if (t1 is FunctionType) return true; | 416 if (t1 is FunctionType) return true; |
412 if (t1.element is ClassElement) { | 417 if (t1.element is ClassElement) { |
413 if ((t1.element as ClassElement).getMethod("call") != null) return true; | 418 if ((t1.element as ClassElement).getMethod("call") != null) return true; |
414 } | 419 } |
415 } | 420 } |
416 | 421 |
417 // "Traditional" name-based subtype check. | 422 // "Traditional" name-based subtype check. |
418 if (t1 is InterfaceType && t2 is InterfaceType) { | 423 if (t1 is InterfaceType && t2 is InterfaceType) { |
419 return _isInterfaceSubTypeOf(t1, t2); | 424 return _isInterfaceSubTypeOf(t1, t2); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 var ok = inferrer.inferExpression(expr, toT, errors); | 511 var ok = inferrer.inferExpression(expr, toT, errors); |
507 if (ok) return InferredType.create(this, expr, toT); | 512 if (ok) return InferredType.create(this, expr, toT); |
508 reason = (errors.isNotEmpty) ? errors.first : null; | 513 reason = (errors.isNotEmpty) ? errors.first : null; |
509 } | 514 } |
510 if (c is Cast) return DownCast.create(this, expr, c, reason: reason); | 515 if (c is Cast) return DownCast.create(this, expr, c, reason: reason); |
511 assert(false); | 516 assert(false); |
512 return null; | 517 return null; |
513 } | 518 } |
514 | 519 |
515 DartType elementType(Element e) { | 520 DartType elementType(Element e) { |
| 521 if (e == null) { |
| 522 // Malformed code - just return dynamic. |
| 523 return provider.dynamicType; |
| 524 } |
516 return (e as dynamic).type; | 525 return (e as dynamic).type; |
517 } | 526 } |
518 | 527 |
519 /// Returns `true` if the target expression is dynamic. | 528 /// Returns `true` if the target expression is dynamic. |
520 // TODO(jmesserly): remove this in favor of utils? Or a static method here? | 529 // TODO(jmesserly): remove this in favor of utils? Or a static method here? |
521 bool isDynamicTarget(Expression target) => utils.isDynamicTarget(target); | 530 bool isDynamicTarget(Expression target) => utils.isDynamicTarget(target); |
522 | 531 |
523 /// Returns `true` if the expression is a dynamic function call or method | 532 /// Returns `true` if the expression is a dynamic function call or method |
524 /// invocation. | 533 /// invocation. |
525 bool isDynamicCall(Expression call) { | 534 bool isDynamicCall(Expression call) { |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 if (rawType is! InterfaceType) return false; | 706 if (rawType is! InterfaceType) return false; |
698 var type = (rawType as InterfaceType); | 707 var type = (rawType as InterfaceType); |
699 if (type.typeParameters == null || | 708 if (type.typeParameters == null || |
700 type.typeParameters.length == 0) return false; | 709 type.typeParameters.length == 0) return false; |
701 if (e.constructorName.type == null) return false; | 710 if (e.constructorName.type == null) return false; |
702 // classTypeName is the type name of the class being instantiated | 711 // classTypeName is the type name of the class being instantiated |
703 var classTypeName = e.constructorName.type; | 712 var classTypeName = e.constructorName.type; |
704 // Check that we were not passed any type arguments | 713 // Check that we were not passed any type arguments |
705 if (classTypeName.typeArguments != null) return false; | 714 if (classTypeName.typeArguments != null) return false; |
706 // Infer type arguments | 715 // Infer type arguments |
| 716 if (t is! InterfaceType) return false; |
707 var targs = _matchTypes(type, t); | 717 var targs = _matchTypes(type, t); |
708 if (targs == null) return false; | 718 if (targs == null) return false; |
709 if (e.staticElement == null) return false; | 719 if (e.staticElement == null) return false; |
710 var constructorElement = e.staticElement; | 720 var constructorElement = e.staticElement; |
711 // From the constructor element get: | 721 // From the constructor element get: |
712 // the instantiated type of the constructor, then | 722 // the instantiated type of the constructor, then |
713 // the uninstantiated element for the constructor, then | 723 // the uninstantiated element for the constructor, then |
714 // the uninstantiated type for the constructor | 724 // the uninstantiated type for the constructor |
715 var rawConstructorElement = | 725 var rawConstructorElement = |
716 constructorElement.type.element as ConstructorElement; | 726 constructorElement.type.element as ConstructorElement; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 var entries = e.entries; | 838 var entries = e.entries; |
829 bool inferEntry(MapLiteralEntry entry) { | 839 bool inferEntry(MapLiteralEntry entry) { |
830 return _inferExpression(entry.key, kType, errors) && | 840 return _inferExpression(entry.key, kType, errors) && |
831 _inferExpression(entry.value, vType, errors); | 841 _inferExpression(entry.value, vType, errors); |
832 } | 842 } |
833 var b = entries.every(inferEntry); | 843 var b = entries.every(inferEntry); |
834 if (b) annotateMapLiteral(e, targs); | 844 if (b) annotateMapLiteral(e, targs); |
835 return b; | 845 return b; |
836 } | 846 } |
837 } | 847 } |
OLD | NEW |