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 30f7821950e7f2954dd871e1a04c48e2c6261dbe..be0ac5dd3c45b6bb144870adb5469b1774102378 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,34 +53,6 @@ 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; |
@@ -1359,7 +1331,7 @@ class KernelMethodInvocation extends MethodInvocation |
// The inference dependencies are the inference dependencies of the |
// receiver. |
collector.collectDependencies(receiver); |
- if (_isOverloadableArithmeticOperator(name.name)) { |
+ if (isOverloadableArithmeticOperator(name.name)) { |
collector.collectDependencies(arguments.positional[0]); |
} |
} |
@@ -1367,39 +1339,8 @@ class KernelMethodInvocation extends MethodInvocation |
@override |
DartType _inferExpression( |
KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
- typeNeeded = inferrer.listener.methodInvocationEnter(this, typeContext) || |
- typeNeeded; |
- // First infer the receiver so we can look up the method that was invoked. |
- var receiverType = inferrer.inferExpression(receiver, null, true); |
- bool isOverloadedArithmeticOperator = false; |
- Member interfaceMember = |
- inferrer.findMethodInvocationMember(receiverType, this); |
- if (interfaceMember is Procedure) { |
- isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment |
- .isOverloadedArithmeticOperatorAndType(interfaceMember, receiverType); |
- } |
- 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, |
- forceArgumentInference: forceArgumentInference); |
- inferrer.listener.methodInvocationExit(this, inferredType); |
- return inferredType; |
+ return inferrer.inferMethodInvocation(this, receiver, fileOffset, this, |
+ _isImplicitCall, typeContext, typeNeeded); |
} |
} |
@@ -1425,6 +1366,44 @@ class KernelNot extends Not implements KernelExpression { |
} |
} |
+/// Concrete shadow object representing a null-aware method invocation. |
+/// |
+/// A null-aware method invocation of the form `a?.b(...)` is represented as the |
+/// expression: |
+/// |
+/// let v = a in v == null ? null : v.b(...) |
+class KernelNullAwareMethodInvocation extends Let implements KernelExpression { |
+ KernelNullAwareMethodInvocation(VariableDeclaration variable, Expression body) |
+ : super(variable, body); |
+ |
+ @override |
+ ConditionalExpression get body => super.body; |
+ |
+ MethodInvocation get _desugaredInvocation => body.otherwise; |
+ |
+ @override |
+ void _collectDependencies(KernelDependencyCollector collector) { |
+ // Null aware expressions are not immediately evident. |
+ collector.recordNotImmediatelyEvident(fileOffset); |
+ } |
+ |
+ @override |
+ DartType _inferExpression( |
+ KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
+ var inferredType = inferrer.inferMethodInvocation( |
+ this, |
+ variable.initializer, |
+ fileOffset, |
+ _desugaredInvocation, |
+ false, |
+ typeContext, |
+ true, |
+ receiverVariable: variable); |
+ body.staticType = inferredType; |
+ return inferredType; |
+ } |
+} |
+ |
/// Concrete shadow object representing a null-aware read from a property. |
/// |
/// A null-aware property get of the form `a?.b` is represented as the kernel |