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

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

Issue 2176693003: Issue a strong mode warning for type inference that is unsafe with AST-based summaries. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 5 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
« no previous file with comments | « pkg/analyzer/lib/src/generated/error.dart ('k') | pkg/analyzer/test/src/summary/resynthesize_ast_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 568bf3069595ddaff612925f49439cd640106c25..86969f58d80dc6bb95991fdd6f593f61cdba3d8e 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -380,6 +380,12 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
+ void visitFunctionExpression(FunctionExpression node) {
+ _checkForUnsafeBlockClosureInference(node);
+ super.visitFunctionExpression(node);
+ }
+
+ @override
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
checkFunctionApplication(node, node.function, node.argumentList);
node.visitChildren(this);
@@ -713,6 +719,71 @@ class CodeChecker extends RecursiveAstVisitor {
node.visitChildren(this);
}
+ /**
+ * Check if the closure [node] is unsafe due to dartbug.com/26947. If so,
+ * issue a warning.
+ *
+ * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed.
+ */
+ void _checkForUnsafeBlockClosureInference(FunctionExpression node) {
+ if (node.body is! BlockFunctionBody) {
+ return;
+ }
+ if (node.element.returnType.isDynamic) {
+ return;
+ }
+ // Find the enclosing variable declaration whose inferred type might depend
+ // on the inferred return type of the block closure (if any).
+ VariableDeclaration decl = null;
+ AstNode ancestor = node.parent;
+ while (ancestor != null) {
+ if (ancestor is BlockFunctionBody) {
+ // node is inside another block function body; if that block
+ // function body is unsafe, we've already warned about it.
+ return;
+ }
+ if (ancestor is VariableDeclaration) {
Leaf 2016/07/22 23:34:41 Might be a bit clearer just to make this part of t
Paul Berry 2016/07/23 16:18:18 Done.
+ decl = ancestor;
+ break;
+ }
+ if (ancestor is InstanceCreationExpression) {
Leaf 2016/07/22 23:34:41 Presumably this same logic could be applied to Lis
Paul Berry 2016/07/23 16:18:18 Done. PTAL.
+ // node appears inside an instance creation expression; we may be safe
+ // if the type of the instance creation expression requires no
+ // inference.
+ TypeName typeName = ancestor.constructorName.type;
+ DartType type = typeName.type;
+ if (typeName.typeArguments != null) {
+ // Type arguments were explicitly specified. We are safe.
+ return;
+ }
+ if (!(type is ParameterizedType && type.typeParameters.isNotEmpty)) {
+ // Type is not generic. We are safe.
+ return;
+ }
+ }
+ ancestor = ancestor.parent;
+ }
+ if (decl == null) {
+ // node is not inside a variable declaration, so it is safe.
+ return;
+ }
+ VariableElement declElement = decl.element;
+ if (!declElement.hasImplicitType) {
+ // Variable declaration has an explicit type, so it's safe.
+ return;
+ }
+ if (declElement.type.isDynamic) {
+ // No type was successfully inferred for this variable, so it's safe.
+ return;
+ }
+ if (declElement.enclosingElement is ExecutableElement) {
+ // Variable declaration is inside a function or method, so it's safe.
+ return;
+ }
+ _recordMessage(node, StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE,
+ [declElement.name]);
+ }
+
void _checkReturnOrYield(Expression expression, AstNode node,
{bool yieldStar: false}) {
FunctionBody body = node.getAncestor((n) => n is FunctionBody);
« no previous file with comments | « pkg/analyzer/lib/src/generated/error.dart ('k') | pkg/analyzer/test/src/summary/resynthesize_ast_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698