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

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

Issue 2221233002: fix #27036, pass definite function types to LUB (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: small refactor for checker & InvocationExpressions 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/task/strong/checker.dart
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 19e1c8c02bbc57e12372d140195c568a86a416b5..2aa5af0c0e077eb0da0425eb76c34592e1d4b0a8 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -29,6 +29,27 @@ bool isKnownFunction(Expression expression) {
element is MethodElement && element.isStatic;
}
+/// Given an [expression] and a corresponding [typeSystem] and [typeProvider],
+/// gets the known static type of the expression.
+///
+/// Normally when we ask for an expression's type, we get the type of the
+/// storage slot that would contain it. For function types, this is necessarily
+/// a "fuzzy arrow" that treats `dynamic` as bottom. However, if we're
+/// interested in the expression's own type, it can often be a "strict arrow"
+/// because we know it evaluates to a specific, concrete function, and we can
+/// treat "dynamic" as top for that case, which is more permissive.
+DartType getDefiniteType(
+ Expression expression, TypeSystem typeSystem, TypeProvider typeProvider) {
+ DartType type = expression.staticType ?? DynamicTypeImpl.instance;
+ if (typeSystem is StrongTypeSystemImpl &&
+ type is FunctionType &&
+ _hasStrictArrow(expression)) {
+ // Remove fuzzy arrow if possible.
+ return typeSystem.functionTypeToConcreteType(typeProvider, type);
+ }
+ return type;
+}
+
bool _hasStrictArrow(Expression expression) {
var element = _getKnownElement(expression);
return element is FunctionElement || element is MethodElement;
@@ -187,14 +208,15 @@ class CodeChecker extends RecursiveAstVisitor {
void checkBoolean(Expression expr) =>
checkAssignment(expr, typeProvider.boolType);
- void checkFunctionApplication(
- Expression node, Expression f, ArgumentList list) {
- if (_isDynamicCall(f)) {
+ void checkFunctionApplication(InvocationExpression node) {
Jennifer Messerly 2016/08/09 12:35:19 fyi -- I did a small refactor in patch set 2, taki
+ var ft = _getTypeAsCaller(node);
+
+ if (_isDynamicCall(node, ft)) {
// If f is Function and this is a method invocation, we should have
// gotten an analyzer error, so no need to issue another error.
- _recordDynamicInvoke(node, f);
+ _recordDynamicInvoke(node, node.function);
} else {
- checkArgumentList(list, _getTypeAsCaller(f));
+ checkArgumentList(node.argumentList, ft);
}
}
@@ -423,7 +445,7 @@ class CodeChecker extends RecursiveAstVisitor {
@override
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- checkFunctionApplication(node, node.function, node.argumentList);
+ checkFunctionApplication(node);
node.visitChildren(this);
}
@@ -551,7 +573,7 @@ class CodeChecker extends RecursiveAstVisitor {
// we call [checkFunctionApplication].
setIsDynamicInvoke(node.methodName, true);
} else {
- checkFunctionApplication(node, node.methodName, node.argumentList);
+ checkFunctionApplication(node);
}
node.visitChildren(this);
}
@@ -969,42 +991,26 @@ class CodeChecker extends RecursiveAstVisitor {
}
}
- DartType _getStaticType(Expression expr) {
- DartType t = expr.staticType ?? DynamicTypeImpl.instance;
-
- // Remove fuzzy arrow if possible.
- if (t is FunctionType && _hasStrictArrow(expr)) {
- t = rules.functionTypeToConcreteType(typeProvider, t);
- }
-
- return t;
- }
+ DartType _getStaticType(Expression expr) =>
vsm 2016/08/10 21:22:21 Maybe rename to _getDefiniteType? The terminology
Jennifer Messerly 2016/08/10 22:28:09 good catch. Done!
+ getDefiniteType(expr, rules, typeProvider);
/// Given an expression, return its type assuming it is
/// in the caller position of a call (that is, accounting
/// for the possibility of a call method). Returns null
/// if expression is not statically callable.
- FunctionType _getTypeAsCaller(Expression node) {
- DartType t = _getStaticType(node);
- if (node is SimpleIdentifier) {
- Expression parent = node.parent;
- if (parent is MethodInvocation) {
- t = parent.staticInvokeType;
- }
- }
- if (t is InterfaceType) {
- return rules.getCallMethodType(t);
- }
- if (t is FunctionType) {
- return t;
+ FunctionType _getTypeAsCaller(InvocationExpression node) {
+ DartType type = node.staticInvokeType;
+ if (type is FunctionType) {
+ return type;
+ } else if (type is InterfaceType) {
+ return rules.getCallMethodType(type);
}
return null;
}
/// Returns `true` if the expression is a dynamic function call or method
/// invocation.
- bool _isDynamicCall(Expression call) {
- var ft = _getTypeAsCaller(call);
+ bool _isDynamicCall(InvocationExpression call, FunctionType ft) {
// TODO(leafp): This will currently return true if t is Function
// This is probably the most correct thing to do for now, since
// this code is also used by the back end. Maybe revisit at some
@@ -1014,7 +1020,7 @@ class CodeChecker extends RecursiveAstVisitor {
// a dynamic parameter type requires a dynamic call in general.
// However, as an optimization, if we have an original definition, we know
// dynamic is reified as Object - in this case a regular call is fine.
- if (_hasStrictArrow(call)) {
+ if (_hasStrictArrow(call.function)) {
return false;
}
return rules.anyParameterType(ft, (pt) => pt.isDynamic);
« no previous file with comments | « pkg/analyzer/lib/src/generated/static_type_analyzer.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