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

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

Issue 2675963004: fix #28630, instance method tear-offs are treated as strict arrows (Closed)
Patch Set: fix sdk Created 3 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';
(...skipping 18 matching lines...) Expand all
29 /// storage slot that would contain it. For function types, this is necessarily 29 /// storage slot that would contain it. For function types, this is necessarily
30 /// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're 30 /// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're
31 /// interested in the expression's own type, it can often be a "strict arrow" 31 /// interested in the expression's own type, it can often be a "strict arrow"
32 /// because we know it evaluates to a specific, concrete function, and we can 32 /// because we know it evaluates to a specific, concrete function, and we can
33 /// treat "dynamic" as top for that case, which is more permissive. 33 /// treat "dynamic" as top for that case, which is more permissive.
34 DartType getDefiniteType( 34 DartType getDefiniteType(
35 Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) { 35 Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) {
36 DartType type = expression.staticType ?? DynamicTypeImpl.instance; 36 DartType type = expression.staticType ?? DynamicTypeImpl.instance;
37 if (typeSystem is StrongTypeSystemImpl && 37 if (typeSystem is StrongTypeSystemImpl &&
38 type is FunctionType && 38 type is FunctionType &&
39 _hasStrictArrow(expression)) { 39 hasStrictArrow(expression)) {
40 // Remove fuzzy arrow if possible. 40 // Remove fuzzy arrow if possible.
41 return typeSystem.functionTypeToConcreteType(type); 41 return typeSystem.functionTypeToConcreteType(type);
42 } 42 }
43 return type; 43 return type;
44 } 44 }
45 45
46 bool isKnownFunction(Expression expression) {
47 var element = _getKnownElement(expression);
48 // First class functions and static methods, where we know the original
49 // declaration, will have an exact type, so we know a downcast will fail.
50 return element is FunctionElement ||
51 element is MethodElement && element.isStatic;
52 }
53
54 DartType _elementType(Element e) { 46 DartType _elementType(Element e) {
55 if (e == null) { 47 if (e == null) {
56 // Malformed code - just return dynamic. 48 // Malformed code - just return dynamic.
57 return DynamicTypeImpl.instance; 49 return DynamicTypeImpl.instance;
58 } 50 }
59 return (e as dynamic).type; 51 return (e as dynamic).type;
60 } 52 }
61 53
62 Element _getKnownElement(Expression expression) { 54 Element _getKnownElement(Expression expression) {
63 if (expression is ParenthesizedExpression) { 55 if (expression is ParenthesizedExpression) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 } 90 }
99 if (field.isSynthetic) return null; 91 if (field.isSynthetic) return null;
100 return field; 92 return field;
101 } 93 }
102 94
103 /// Looks up the declaration that matches [member] in [type] and returns it's 95 /// Looks up the declaration that matches [member] in [type] and returns it's
104 /// declared type. 96 /// declared type.
105 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) => 97 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) =>
106 _memberTypeGetter(member)(type); 98 _memberTypeGetter(member)(type);
107 99
108 bool _hasStrictArrow(Expression expression) { 100 bool hasStrictArrow(Expression expression) {
109 var element = _getKnownElement(expression); 101 var element = _getKnownElement(expression);
110 return element is FunctionElement || element is MethodElement; 102 return element is FunctionElement || element is MethodElement;
111 } 103 }
112 104
113 _MemberTypeGetter _memberTypeGetter(ExecutableElement member) { 105 _MemberTypeGetter _memberTypeGetter(ExecutableElement member) {
114 String memberName = member.name; 106 String memberName = member.name;
115 final isGetter = member is PropertyAccessorElement && member.isGetter; 107 final isGetter = member is PropertyAccessorElement && member.isGetter;
116 final isSetter = member is PropertyAccessorElement && member.isSetter; 108 final isSetter = member is PropertyAccessorElement && member.isSetter;
117 109
118 FunctionType f(InterfaceType type) { 110 FunctionType f(InterfaceType type) {
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 bool _isDynamicCall(InvocationExpression call, FunctionType ft) { 987 bool _isDynamicCall(InvocationExpression call, FunctionType ft) {
996 // TODO(leafp): This will currently return true if t is Function 988 // TODO(leafp): This will currently return true if t is Function
997 // This is probably the most correct thing to do for now, since 989 // This is probably the most correct thing to do for now, since
998 // this code is also used by the back end. Maybe revisit at some 990 // this code is also used by the back end. Maybe revisit at some
999 // point? 991 // point?
1000 if (ft == null) return true; 992 if (ft == null) return true;
1001 // Dynamic as the parameter type is treated as bottom. A function with 993 // Dynamic as the parameter type is treated as bottom. A function with
1002 // a dynamic parameter type requires a dynamic call in general. 994 // a dynamic parameter type requires a dynamic call in general.
1003 // However, as an optimization, if we have an original definition, we know 995 // However, as an optimization, if we have an original definition, we know
1004 // dynamic is reified as Object - in this case a regular call is fine. 996 // dynamic is reified as Object - in this case a regular call is fine.
1005 if (_hasStrictArrow(call.function)) { 997 if (hasStrictArrow(call.function)) {
1006 return false; 998 return false;
1007 } 999 }
1008 return rules.anyParameterType(ft, (pt) => pt.isDynamic); 1000 return rules.anyParameterType(ft, (pt) => pt.isDynamic);
1009 } 1001 }
1010 1002
1011 /// Returns true if we need an implicit cast of [expr] from [from] type to 1003 /// Returns true if we need an implicit cast of [expr] from [from] type to
1012 /// [to] type, otherwise returns false. 1004 /// [to] type, otherwise returns false.
1013 /// 1005 ///
1014 /// If [from] is omitted, uses the static type of [expr]. 1006 /// If [from] is omitted, uses the static type of [expr].
1015 bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) { 1007 bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 if (expr is InstanceCreationExpression) { 1075 if (expr is InstanceCreationExpression) {
1084 ConstructorElement e = expr.staticElement; 1076 ConstructorElement e = expr.staticElement;
1085 if (e == null || !e.isFactory) { 1077 if (e == null || !e.isFactory) {
1086 // fromT should be an exact type - this will almost certainly fail at 1078 // fromT should be an exact type - this will almost certainly fail at
1087 // runtime. 1079 // runtime.
1088 _recordMessage(expr, StrongModeCode.INVALID_CAST_NEW_EXPR, [from, to]); 1080 _recordMessage(expr, StrongModeCode.INVALID_CAST_NEW_EXPR, [from, to]);
1089 return; 1081 return;
1090 } 1082 }
1091 } 1083 }
1092 1084
1093 if (isKnownFunction(expr)) { 1085 Element e = _getKnownElement(expr);
1094 Element e = _getKnownElement(expr); 1086 if (e is FunctionElement || e is MethodElement && e.isStatic) {
1095 _recordMessage( 1087 _recordMessage(
1096 expr, 1088 expr,
1097 e is MethodElement 1089 e is MethodElement
1098 ? StrongModeCode.INVALID_CAST_METHOD 1090 ? StrongModeCode.INVALID_CAST_METHOD
1099 : StrongModeCode.INVALID_CAST_FUNCTION, 1091 : StrongModeCode.INVALID_CAST_FUNCTION,
1100 [e.name, from, to]); 1092 [e.name, from, to]);
1101 return; 1093 return;
1102 } 1094 }
1103 1095
1104 // Composite cast: these are more likely to fail. 1096 // Composite cast: these are more likely to fail.
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1500 var visited = new Set<InterfaceType>(); 1492 var visited = new Set<InterfaceType>();
1501 do { 1493 do {
1502 visited.add(current); 1494 visited.add(current);
1503 current.mixins.reversed.forEach( 1495 current.mixins.reversed.forEach(
1504 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1496 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1505 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1497 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1506 current = current.superclass; 1498 current = current.superclass;
1507 } while (!current.isObject && !visited.contains(current)); 1499 } while (!current.isObject && !visited.contains(current));
1508 } 1500 }
1509 } 1501 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/error_verifier.dart ('k') | pkg/analyzer/test/src/task/strong/checker_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698