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

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

Issue 2211053002: fix #26962, invoking a known lambda is not a dynamic invoke (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix comment Created 4 years, 4 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
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/strong/inferred_type_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 TokenType; 11 import 'package:analyzer/dart/ast/token.dart' show TokenType;
12 import 'package:analyzer/dart/ast/token.dart'; 12 import 'package:analyzer/dart/ast/token.dart';
13 import 'package:analyzer/dart/ast/visitor.dart'; 13 import 'package:analyzer/dart/ast/visitor.dart';
14 import 'package:analyzer/dart/element/element.dart'; 14 import 'package:analyzer/dart/element/element.dart';
15 import 'package:analyzer/dart/element/type.dart'; 15 import 'package:analyzer/dart/element/type.dart';
16 import 'package:analyzer/src/dart/element/type.dart'; 16 import 'package:analyzer/src/dart/element/type.dart';
17 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl; 17 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
18 import 'package:analyzer/src/generated/error.dart' show StrongModeCode; 18 import 'package:analyzer/src/generated/error.dart' show StrongModeCode;
19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
20 import 'package:analyzer/src/generated/type_system.dart'; 20 import 'package:analyzer/src/generated/type_system.dart';
21 21
22 import 'ast_properties.dart'; 22 import 'ast_properties.dart';
23 23
24 bool isKnownFunction(Expression expression) { 24 bool isKnownFunction(Expression expression, {bool instanceMethods: false}) {
25 Element element = null; 25 Element element = null;
26 if (expression is ParenthesizedExpression) {
27 expression = (expression as ParenthesizedExpression).expression;
28 }
26 if (expression is FunctionExpression) { 29 if (expression is FunctionExpression) {
27 return true; 30 return true;
28 } else if (expression is PropertyAccess) { 31 } else if (expression is PropertyAccess) {
29 element = expression.propertyName.staticElement; 32 element = expression.propertyName.staticElement;
30 } else if (expression is Identifier) { 33 } else if (expression is Identifier) {
31 element = expression.staticElement; 34 element = expression.staticElement;
32 } 35 }
33 // First class functions and static methods, where we know the original 36 // First class functions and static methods, where we know the original
34 // declaration, will have an exact type, so we know a downcast will fail. 37 // declaration, will have an exact type, so we know a downcast will fail.
35 return element is FunctionElement || 38 return element is FunctionElement ||
36 element is MethodElement && element.isStatic; 39 element is MethodElement && (instanceMethods || element.isStatic);
37 } 40 }
38 41
39 DartType _elementType(Element e) { 42 DartType _elementType(Element e) {
40 if (e == null) { 43 if (e == null) {
41 // Malformed code - just return dynamic. 44 // Malformed code - just return dynamic.
42 return DynamicTypeImpl.instance; 45 return DynamicTypeImpl.instance;
43 } 46 }
44 return (e as dynamic).type; 47 return (e as dynamic).type;
45 } 48 }
46 49
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 if (type.isDynamic) { 932 if (type.isDynamic) {
930 return type; 933 return type;
931 } else if (type is InterfaceType && type.element == expectedType.element) { 934 } else if (type is InterfaceType && type.element == expectedType.element) {
932 return type.typeArguments[0]; 935 return type.typeArguments[0];
933 } else { 936 } else {
934 // Malformed type - fallback on analyzer error. 937 // Malformed type - fallback on analyzer error.
935 return null; 938 return null;
936 } 939 }
937 } 940 }
938 941
939 // Produce a coercion which coerces something of type fromT
940 // to something of type toT.
941 // Returns the error coercion if the types cannot be coerced
942 // according to our current criteria.
943 DartType _getStaticType(Expression expr) { 942 DartType _getStaticType(Expression expr) {
944 DartType t = expr.staticType ?? DynamicTypeImpl.instance; 943 DartType t = expr.staticType ?? DynamicTypeImpl.instance;
945 944
946 // Remove fuzzy arrow if possible. 945 // Remove fuzzy arrow if possible.
947 if (t is FunctionType && isKnownFunction(expr)) { 946 if (t is FunctionType && isKnownFunction(expr)) {
948 t = rules.functionTypeToConcreteType(typeProvider, t); 947 t = rules.functionTypeToConcreteType(typeProvider, t);
949 } 948 }
950 949
951 return t; 950 return t;
952 } 951 }
(...skipping 25 matching lines...) Expand all
978 var ft = _getTypeAsCaller(call); 977 var ft = _getTypeAsCaller(call);
979 // TODO(leafp): This will currently return true if t is Function 978 // TODO(leafp): This will currently return true if t is Function
980 // This is probably the most correct thing to do for now, since 979 // This is probably the most correct thing to do for now, since
981 // this code is also used by the back end. Maybe revisit at some 980 // this code is also used by the back end. Maybe revisit at some
982 // point? 981 // point?
983 if (ft == null) return true; 982 if (ft == null) return true;
984 // Dynamic as the parameter type is treated as bottom. A function with 983 // Dynamic as the parameter type is treated as bottom. A function with
985 // a dynamic parameter type requires a dynamic call in general. 984 // a dynamic parameter type requires a dynamic call in general.
986 // However, as an optimization, if we have an original definition, we know 985 // However, as an optimization, if we have an original definition, we know
987 // dynamic is reified as Object - in this case a regular call is fine. 986 // dynamic is reified as Object - in this case a regular call is fine.
988 if (call is SimpleIdentifier) { 987 if (isKnownFunction(call, instanceMethods: true)) {
989 var element = call.staticElement; 988 return false;
990 if (element is FunctionElement || element is MethodElement) {
991 // An original declaration.
992 return false;
993 }
994 } 989 }
995
996 return rules.anyParameterType(ft, (pt) => pt.isDynamic); 990 return rules.anyParameterType(ft, (pt) => pt.isDynamic);
997 } 991 }
998 992
999 /// Returns `true` if the target expression is dynamic. 993 /// Returns `true` if the target expression is dynamic.
1000 bool _isDynamicTarget(Expression node) { 994 bool _isDynamicTarget(Expression node) {
1001 if (node == null) return false; 995 if (node == null) return false;
1002 996
1003 if (_isLibraryPrefix(node)) return false; 997 if (_isLibraryPrefix(node)) return false;
1004 998
1005 // Null type happens when we have unknown identifiers, like a dart: import 999 // Null type happens when we have unknown identifiers, like a dart: import
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
1489 var visited = new Set<InterfaceType>(); 1483 var visited = new Set<InterfaceType>();
1490 do { 1484 do {
1491 visited.add(current); 1485 visited.add(current);
1492 current.mixins.reversed.forEach( 1486 current.mixins.reversed.forEach(
1493 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1487 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1494 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1488 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1495 current = current.superclass; 1489 current = current.superclass;
1496 } while (!current.isObject && !visited.contains(current)); 1490 } while (!current.isObject && !visited.contains(current));
1497 } 1491 }
1498 } 1492 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/strong/inferred_type_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698