Chromium Code Reviews| 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 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 void annotateMapLiteral(MapLiteral e, List<DartType> targs) {} | 563 void annotateMapLiteral(MapLiteral e, List<DartType> targs) {} |
| 564 | 564 |
| 565 /// Called for each new/const which gets inferred | 565 /// Called for each new/const which gets inferred |
| 566 void annotateInstanceCreationExpression( | 566 void annotateInstanceCreationExpression( |
| 567 InstanceCreationExpression e, List<DartType> targs) {} | 567 InstanceCreationExpression e, List<DartType> targs) {} |
| 568 | 568 |
| 569 /// Downward inference | 569 /// Downward inference |
| 570 bool inferExpression(Expression e, DartType t) { | 570 bool inferExpression(Expression e, DartType t) { |
| 571 if (e is Conversion) return inferExpression(e.node, t); | 571 if (e is Conversion) return inferExpression(e.node, t); |
| 572 if (rules.isSubTypeOf(rules.getStaticType(e), t)) return true; | 572 if (rules.isSubTypeOf(rules.getStaticType(e), t)) return true; |
| 573 if (e is FunctionExpression) return _inferFunctionExpression(e, t); | |
| 573 if (e is ListLiteral) return _inferListLiteral(e, t); | 574 if (e is ListLiteral) return _inferListLiteral(e, t); |
| 574 if (e is MapLiteral) return _inferMapLiteral(e, t); | 575 if (e is MapLiteral) return _inferMapLiteral(e, t); |
| 575 if (e is NamedExpression) return _inferNamedExpression(e, t); | 576 if (e is NamedExpression) return _inferNamedExpression(e, t); |
| 576 if (e is InstanceCreationExpression) return _inferInstanceCreationExpression ( | 577 if (e is InstanceCreationExpression) return _inferInstanceCreationExpression ( |
| 577 e, t); | 578 e, t); |
| 578 return false; | 579 return false; |
| 579 } | 580 } |
| 580 | 581 |
| 581 /// If t1 = I<dynamic, ..., dynamic>, then look for a supertype | 582 /// If t1 = I<dynamic, ..., dynamic>, then look for a supertype |
| 582 /// of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'> | 583 /// of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'> |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 } | 717 } |
| 717 } | 718 } |
| 718 annotateInstanceCreationExpression(e, targs); | 719 annotateInstanceCreationExpression(e, targs); |
| 719 return true; | 720 return true; |
| 720 } | 721 } |
| 721 | 722 |
| 722 bool _inferNamedExpression(NamedExpression e, DartType t) { | 723 bool _inferNamedExpression(NamedExpression e, DartType t) { |
| 723 return inferExpression(e.expression, t); | 724 return inferExpression(e.expression, t); |
| 724 } | 725 } |
| 725 | 726 |
| 727 bool _inferFunctionExpression(FunctionExpression e, DartType t) { | |
| 728 if (t is! FunctionType) return false; | |
| 729 var returnT = (t as FunctionType).returnType; | |
| 730 if (returnT.isDynamic) return false; | |
|
vsm
2015/04/01 00:14:19
Why do we disallow this?
In this case,
typedef F
Leaf
2015/04/03 00:51:55
Eventually, yes. As it stands, no. I don't impro
| |
| 731 var eType = e.staticType; | |
| 732 if (eType is! FunctionType) return false; | |
| 733 if (e.body is! ExpressionFunctionBody) return false; | |
| 734 var body = (e.body as ExpressionFunctionBody).expression; | |
| 735 if (!inferExpression(body, returnT)) return false; | |
| 736 // TODO(leafp): Try narrowing the argument types if possible | |
| 737 // to get better code in the function body. This requires checking | |
| 738 // that the body is well-typed at the more specific type. | |
| 739 (e.element as ExecutableElementImpl).returnType = returnT; | |
| 740 // Work around dynamic as bottom for now by handling function literals | |
| 741 // with dynamic arguments specially. We already know the body is typable | |
| 742 // at the chosen type, and if all args are dynamic, then function must be | |
| 743 // typeable. | |
| 744 if ((eType as FunctionType).parameters.every((x) => x.type.isDynamic)) { | |
| 745 return true; | |
| 746 } | |
| 747 return rules.isSubTypeOf(e.staticType, t); | |
|
vsm
2015/04/01 00:14:19
Should we have changed e.element.returnType if the
Leaf
2015/04/03 00:51:55
Probably not. Probably doesn't matter, but still
| |
| 748 } | |
| 749 | |
| 726 bool _inferListLiteral(ListLiteral e, DartType t) { | 750 bool _inferListLiteral(ListLiteral e, DartType t) { |
| 727 var dyn = rules.provider.dynamicType; | 751 var dyn = rules.provider.dynamicType; |
| 728 var listT = rules.provider.listType.substitute4([dyn]); | 752 var listT = rules.provider.listType.substitute4([dyn]); |
| 729 // List <: t (using dart rules) must be true | 753 // List <: t (using dart rules) must be true |
| 730 if (!listT.isSubtypeOf(t)) return false; | 754 if (!listT.isSubtypeOf(t)) return false; |
| 731 // The list literal must have no type arguments | 755 // The list literal must have no type arguments |
| 732 if (e.typeArguments != null) return false; | 756 if (e.typeArguments != null) return false; |
| 733 if (t is! InterfaceType) return false; | 757 if (t is! InterfaceType) return false; |
| 734 var targs = _matchTypes(listT, t); | 758 var targs = _matchTypes(listT, t); |
| 735 if (targs == null) return false; | 759 if (targs == null) return false; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 759 var entries = e.entries; | 783 var entries = e.entries; |
| 760 bool inferEntry(MapLiteralEntry entry) { | 784 bool inferEntry(MapLiteralEntry entry) { |
| 761 return inferExpression(entry.key, kType) && | 785 return inferExpression(entry.key, kType) && |
| 762 inferExpression(entry.value, vType); | 786 inferExpression(entry.value, vType); |
| 763 } | 787 } |
| 764 var b = entries.every(inferEntry); | 788 var b = entries.every(inferEntry); |
| 765 if (b) annotateMapLiteral(e, targs); | 789 if (b) annotateMapLiteral(e, targs); |
| 766 return b; | 790 return b; |
| 767 } | 791 } |
| 768 } | 792 } |
| OLD | NEW |