Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 1700523002: fixes #24507, allow known functions to be treated as strict arrows (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be
6 // refactored to fit into analyzer. 6 // refactored to fit into analyzer.
7 library analyzer.src.task.strong.checker; 7 library analyzer.src.task.strong.checker;
8 8
9 import 'package:analyzer/analyzer.dart'; 9 import 'package:analyzer/analyzer.dart';
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
11 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 11 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
12 import 'package:analyzer/dart/ast/visitor.dart'; 12 import 'package:analyzer/dart/ast/visitor.dart';
13 import 'package:analyzer/dart/element/element.dart'; 13 import 'package:analyzer/dart/element/element.dart';
14 import 'package:analyzer/dart/element/type.dart'; 14 import 'package:analyzer/dart/element/type.dart';
15 import 'package:analyzer/src/dart/element/element.dart';
15 import 'package:analyzer/src/dart/element/type.dart'; 16 import 'package:analyzer/src/dart/element/type.dart';
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/type_system.dart'; 18 import 'package:analyzer/src/generated/type_system.dart';
18 19
19 import 'info.dart'; 20 import 'info.dart';
20 21
21 DartType _elementType(Element e) { 22 DartType _elementType(Element e) {
22 if (e == null) { 23 if (e == null) {
23 // Malformed code - just return dynamic. 24 // Malformed code - just return dynamic.
24 return DynamicTypeImpl.instance; 25 return DynamicTypeImpl.instance;
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 node.visitChildren(this); 559 node.visitChildren(this);
559 } 560 }
560 561
561 @override 562 @override
562 void visitYieldStatement(YieldStatement node) { 563 void visitYieldStatement(YieldStatement node) {
563 _checkReturnOrYield(node.expression, node, yieldStar: node.star != null); 564 _checkReturnOrYield(node.expression, node, yieldStar: node.star != null);
564 node.visitChildren(this); 565 node.visitChildren(this);
565 } 566 }
566 567
567 StaticInfo _checkAssignment(Expression expr, DartType toT) { 568 StaticInfo _checkAssignment(Expression expr, DartType toT) {
568 final fromT = expr.staticType ?? DynamicTypeImpl.instance; 569 final fromT = _getStaticType(expr);
569 final Coercion c = _coerceTo(fromT, toT); 570 final Coercion c = _coerceTo(fromT, toT);
570 if (c is Identity) return null; 571 if (c is Identity) return null;
571 if (c is CoercionError) return new StaticTypeError(rules, expr, toT); 572 if (c is CoercionError) return new StaticTypeError(rules, expr, toT);
572 if (c is Cast) return DownCast.create(rules, expr, c); 573 if (c is Cast) return DownCast.create(rules, expr, c);
573 assert(false); 574 assert(false);
574 return null; 575 return null;
575 } 576 }
576 577
577 void _checkCompoundAssignment(AssignmentExpression expr) { 578 void _checkCompoundAssignment(AssignmentExpression expr) {
578 var op = expr.operator.type; 579 var op = expr.operator.type;
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 return type; 764 return type;
764 } else if (type is InterfaceType && type.element == expectedType.element) { 765 } else if (type is InterfaceType && type.element == expectedType.element) {
765 return type.typeArguments[0]; 766 return type.typeArguments[0];
766 } else { 767 } else {
767 // Malformed type - fallback on analyzer error. 768 // Malformed type - fallback on analyzer error.
768 return null; 769 return null;
769 } 770 }
770 } 771 }
771 772
772 DartType _getStaticType(Expression expr) { 773 DartType _getStaticType(Expression expr) {
773 return expr.staticType ?? DynamicTypeImpl.instance; 774 DartType t = expr.staticType ?? DynamicTypeImpl.instance;
775
776 // Remove fuzzy arrow if possible.
777 if (t is FunctionType && StaticInfo.isKnownFunction(expr)) {
778 t = _removeFuzz(t);
779 }
780
781 return t;
782 }
783
784 /// Remove "fuzzy arrow" in this function type.
785 ///
786 /// Normally we treat dynamically typed parameters as bottom for function
787 /// types. This allows type tests such as `if (f is SingleArgFunction)`.
788 /// It also requires a dynamic check on the parameter type to call these
789 /// functions.
790 ///
791 /// When we convert to a strict arrow, dynamically typed parameters become
792 /// top. This is safe to do for known functions, like top-level or local
793 /// functions and static methods. Those functions must already be essentially
794 /// treating dynamic as top.
795 ///
796 /// Only the outer-most arrow can be strict. Any others must be fuzzy, because
797 /// we don't know what function value will be passed there.
798 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function
799 // type? That would allow us to implement this in the subtype relation.
800 // TODO(jmesserly): we'll need to factor this differently if we want to
801 // move CodeChecker's functionality into existing analyzer. Likely we can
802 // let the Expression have a strict arrow, then in places were we do
803 // inference, convert back to a fuzzy arrow.
804 FunctionType _removeFuzz(FunctionType t) {
805 bool foundFuzz = false;
806 List<ParameterElement> parameters = <ParameterElement>[];
807 for (ParameterElement p in t.parameters) {
808 ParameterElement newP = _removeParameterFuzz(p);
809 parameters.add(newP);
810 if (p != newP) foundFuzz = true;
811 }
812 if (!foundFuzz) {
813 return t;
814 }
815
816 FunctionElementImpl function = new FunctionElementImpl("", -1);
817 function.synthetic = true;
818 function.returnType = t.returnType;
819 function.shareTypeParameters(t.typeFormals);
820 function.shareParameters(parameters);
821 return function.type = new FunctionTypeImpl(function);
822 }
823
824 /// Removes fuzzy arrow, see [_removeFuzz].
825 ParameterElement _removeParameterFuzz(ParameterElement p) {
826 if (p.type.isDynamic) {
827 return new ParameterElementImpl.synthetic(
828 p.name, typeProvider.objectType, p.parameterKind);
829 }
830 return p;
774 } 831 }
775 832
776 /// Given an expression, return its type assuming it is 833 /// Given an expression, return its type assuming it is
777 /// in the caller position of a call (that is, accounting 834 /// in the caller position of a call (that is, accounting
778 /// for the possibility of a call method). Returns null 835 /// for the possibility of a call method). Returns null
779 /// if expression is not statically callable. 836 /// if expression is not statically callable.
780 FunctionType _getTypeAsCaller(Expression node) { 837 FunctionType _getTypeAsCaller(Expression node) {
781 DartType t = node.staticType; 838 DartType t = node.staticType;
782 if (node is SimpleIdentifier) { 839 if (node is SimpleIdentifier) {
783 Expression parent = node.parent; 840 Expression parent = node.parent;
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 } while (!current.isObject && !visited.contains(current)); 1276 } while (!current.isObject && !visited.contains(current));
1220 } 1277 }
1221 1278
1222 void _recordMessage(StaticInfo info) { 1279 void _recordMessage(StaticInfo info) {
1223 if (info == null) return; 1280 if (info == null) return;
1224 var error = info.toAnalysisError(); 1281 var error = info.toAnalysisError();
1225 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; 1282 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true;
1226 _reporter.onError(error); 1283 _reporter.onError(error);
1227 } 1284 }
1228 } 1285 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/type_system.dart ('k') | pkg/analyzer/lib/src/task/strong/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698