Index: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
index c737ffde591c8992bfb29bb026be49b92f78f1be..5eea63328e1fb554cb1da106f990624b210683e0 100644 |
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
@@ -53,6 +53,34 @@ List<DartType> getExplicitTypeArguments(Arguments arguments) { |
} |
} |
+bool _isOverloadableArithmeticOperator(String name) { |
+ return identical(name, '+') || |
+ identical(name, '-') || |
+ identical(name, '*') || |
+ identical(name, '%'); |
+} |
+ |
+bool _isUserDefinableOperator(String name) { |
+ return identical(name, '<') || |
+ identical(name, '>') || |
+ identical(name, '<=') || |
+ identical(name, '>=') || |
+ identical(name, '==') || |
+ identical(name, '-') || |
+ identical(name, '+') || |
+ identical(name, '/') || |
+ identical(name, '~/') || |
+ identical(name, '*') || |
+ identical(name, '%') || |
+ identical(name, '|') || |
+ identical(name, '^') || |
+ identical(name, '&') || |
+ identical(name, '<<') || |
+ identical(name, '>>') || |
+ identical(name, '[]=') || |
+ identical(name, '~'); |
+} |
+ |
/// Concrete shadow object representing a set of invocation arguments. |
class KernelArguments extends Arguments { |
bool _hasExplicitTypeArguments; |
@@ -756,11 +784,13 @@ class KernelFunctionDeclaration extends FunctionDeclaration |
inferrer.inferExpression(parameter.initializer, parameter.type, false); |
} |
} |
- var oldClosureContext = inferrer.closureContext; |
- inferrer.closureContext = |
- new ClosureContext(inferrer, function.asyncMarker, function.returnType); |
- inferrer.inferStatement(function.body); |
- inferrer.closureContext = oldClosureContext; |
+ if (!inferrer.isTopLevel) { |
+ var oldClosureContext = inferrer.closureContext; |
+ inferrer.closureContext = new ClosureContext( |
+ inferrer, function.asyncMarker, function.returnType); |
+ inferrer.inferStatement(function.body); |
+ inferrer.closureContext = oldClosureContext; |
+ } |
inferrer.listener.functionDeclarationExit(this); |
} |
} |
@@ -1273,10 +1303,7 @@ class KernelMethodInvocation extends MethodInvocation |
// The inference dependencies are the inference dependencies of the |
// receiver. |
collector.collectDependencies(receiver); |
- if (identical(name, '+') || |
- identical(name, '-') || |
- identical(name, '*') || |
- identical(name, '%')) { |
+ if (_isOverloadableArithmeticOperator(name.name)) { |
collector.collectDependencies(arguments.positional[0]); |
} |
} |
@@ -1297,10 +1324,24 @@ class KernelMethodInvocation extends MethodInvocation |
} |
var calleeType = inferrer.getCalleeFunctionType( |
interfaceMember, receiverType, name, !_isImplicitCall); |
+ bool forceArgumentInference = false; |
+ if (inferrer.isDryRun) { |
+ if (_isUserDefinableOperator(name.name)) { |
+ // If this is an overloadable arithmetic operator, then type inference |
+ // might depend on the RHS, so conservatively assume it does. |
+ forceArgumentInference = _isOverloadableArithmeticOperator(name.name); |
+ } else { |
+ // If no type arguments were given, then type inference might depend on |
+ // the arguments (because the called method might be generic), so |
+ // conservatively assume it does. |
+ forceArgumentInference = getExplicitTypeArguments(arguments) == null; |
+ } |
+ } |
var inferredType = inferrer.inferInvocation(typeContext, typeNeeded, |
fileOffset, calleeType, calleeType.returnType, arguments, |
isOverloadedArithmeticOperator: isOverloadedArithmeticOperator, |
- receiverType: receiverType); |
+ receiverType: receiverType, |
+ forceArgumentInference: forceArgumentInference); |
inferrer.listener.methodInvocationExit(this, inferredType); |
return inferredType; |
} |
@@ -1378,6 +1419,14 @@ class KernelPropertyAssign extends KernelComplexAssignmentWithReceiver { |
Member writeMember; |
if (write != null) { |
writeMember = inferrer.findPropertySetMember(receiverType, write); |
+ if (inferrer.isTopLevel && |
+ ((writeMember is Procedure && |
+ writeMember.kind == ProcedureKind.Setter) || |
+ writeMember is Field)) { |
+ // References to fields and setters can't be relied upon for top level |
+ // inference. |
+ inferrer.recordNotImmediatelyEvident(fileOffset); |
+ } |
} |
// To replicate analyzer behavior, we base type inference on the write |
// member. TODO(paulberry): would it be better to use the read member when |
@@ -1554,6 +1603,12 @@ class KernelStaticAssignment extends KernelComplexAssignment { |
var write = this.write; |
if (write is StaticSet) { |
writeContext = write.target.setterType; |
+ if (inferrer.isDryRun) { |
+ var target = write.target; |
+ if (target is KernelField && target._fieldNode != null) { |
+ inferrer.recordDryRunDependency(target._fieldNode); |
+ } |
+ } |
} |
var inferredType = _inferRhs(inferrer, writeContext); |
inferrer.listener.staticAssignExit(desugared, inferredType); |
@@ -1590,6 +1645,12 @@ class KernelStaticGet extends StaticGet implements KernelExpression { |
KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
typeNeeded = |
inferrer.listener.staticGetEnter(this, typeContext) || typeNeeded; |
+ if (inferrer.isDryRun) { |
+ var target = this.target; |
+ if (target is KernelField && target._fieldNode != null) { |
+ inferrer.recordDryRunDependency(target._fieldNode); |
+ } |
+ } |
var inferredType = typeNeeded ? target.getterType : null; |
inferrer.listener.staticGetExit(this, inferredType); |
return inferredType; |
@@ -1901,6 +1962,11 @@ class KernelTypeInferrer extends TypeInferrerImpl { |
@override |
DartType inferExpression( |
Expression expression, DartType typeContext, bool typeNeeded) { |
+ // When doing top level inference, we skip subexpressions whose type isn't |
+ // needed so that we don't induce bogus dependencies on fields mentioned in |
+ // those subexpressions. |
+ if (!typeNeeded && isTopLevel) return null; |
+ |
if (expression is KernelExpression) { |
// Use polymorphic dispatch on [KernelExpression] to perform whatever kind |
// of type inference is correct for this kind of statement. |