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

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/visitor.dart'; 11 import 'package:analyzer/dart/ast/visitor.dart';
12 import 'package:analyzer/dart/element/element.dart'; 12 import 'package:analyzer/dart/element/element.dart';
13 import 'package:analyzer/dart/element/type.dart'; 13 import 'package:analyzer/dart/element/type.dart';
14 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/element/type.dart'; 15 import 'package:analyzer/src/dart/element/type.dart';
15 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 16 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
16 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType; 17 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
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.
(...skipping 534 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 var reason = null; 573 var reason = null;
573 574
574 var errors = <String>[]; 575 var errors = <String>[];
575 576
576 var ok = _inferExpression(expr, toT, errors); 577 var ok = _inferExpression(expr, toT, errors);
577 if (ok) return InferredType.create(rules, expr, toT); 578 if (ok) return InferredType.create(rules, expr, toT);
578 reason = (errors.isNotEmpty) ? errors.first : null; 579 reason = (errors.isNotEmpty) ? errors.first : null;
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 return type; 772 return type;
772 } else if (type is InterfaceType && type.element == expectedType.element) { 773 } else if (type is InterfaceType && type.element == expectedType.element) {
773 return type.typeArguments[0]; 774 return type.typeArguments[0];
774 } else { 775 } else {
775 // Malformed type - fallback on analyzer error. 776 // Malformed type - fallback on analyzer error.
776 return null; 777 return null;
777 } 778 }
778 } 779 }
779 780
780 DartType _getStaticType(Expression expr) { 781 DartType _getStaticType(Expression expr) {
781 return expr.staticType ?? DynamicTypeImpl.instance; 782 DartType t = expr.staticType ?? DynamicTypeImpl.instance;
783
784 // Remove fuzzy arrow if possible.
785 if (t is FunctionType && StaticInfo.isKnownFunction(expr)) {
786 t = _removeFuzz(t);
787 }
788
789 return t;
790 }
791
792 /// Remove "fuzzy arrow" in this function type.
793 ///
794 /// Normally we treat dynamically typed parameters as bottom for function
795 /// types. This allows type tests such as `if (f is SingleArgFunction)`.
796 /// It also requires a dynamic check on the parameter type to call these
797 /// functions.
798 ///
799 /// When we convert to a strict arrow, dynamically typed parameters become
800 /// top. This is safe to do for known functions, like top-level or local
801 /// functions and static methods. Those functions must already be essentially
802 /// treating dynamic as top.
803 ///
804 /// Only the outer-most arrow can be strict. Any others must be fuzzy, because
805 /// we don't know what function value will be passed there.
806 FunctionType _removeFuzz(FunctionType t) {
807 bool foundFuzz = false;
808 List<ParameterElement> parameters = <ParameterElement>[];
809 for (ParameterElement p in t.parameters) {
810 ParameterElement newP = _removeParameterFuzz(p);
811 parameters.add(newP);
812 if (p != newP) foundFuzz = true;
813 }
814 if (!foundFuzz) {
815 return t;
816 }
817
818 FunctionElementImpl function = new FunctionElementImpl("", -1);
819 function.synthetic = true;
820 function.returnType = t.returnType;
821 function.shareTypeParameters(t.typeFormals);
822 function.shareParameters(parameters);
823 return function.type = new FunctionTypeImpl(function);
824 }
825
826 /// Removes fuzzy arrow, see [_removeFuzz].
827 ParameterElement _removeParameterFuzz(ParameterElement p) {
828 if (p.type.isDynamic) {
829 return new ParameterElementImpl.synthetic(
830 p.name, typeProvider.objectType, p.parameterKind);
831 }
832 return p;
782 } 833 }
783 834
784 /// Given an expression, return its type assuming it is 835 /// Given an expression, return its type assuming it is
785 /// in the caller position of a call (that is, accounting 836 /// in the caller position of a call (that is, accounting
786 /// for the possibility of a call method). Returns null 837 /// for the possibility of a call method). Returns null
787 /// if expression is not statically callable. 838 /// if expression is not statically callable.
788 FunctionType _getTypeAsCaller(Expression node) { 839 FunctionType _getTypeAsCaller(Expression node) {
789 DartType t = node.staticType; 840 DartType t = node.staticType;
790 if (node is SimpleIdentifier) { 841 if (node is SimpleIdentifier) {
791 Expression parent = node.parent; 842 Expression parent = node.parent;
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 } while (!current.isObject && !visited.contains(current)); 1289 } while (!current.isObject && !visited.contains(current));
1239 } 1290 }
1240 1291
1241 void _recordMessage(StaticInfo info) { 1292 void _recordMessage(StaticInfo info) {
1242 if (info == null) return; 1293 if (info == null) return;
1243 var error = info.toAnalysisError(); 1294 var error = info.toAnalysisError();
1244 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true; 1295 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true;
1245 _reporter.onError(error); 1296 _reporter.onError(error);
1246 } 1297 }
1247 } 1298 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698