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

Unified Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Issue 2926763003: Add type inference for complex assignments whose LHS is an index expression. (Closed)
Patch Set: Created 3 years, 6 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/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 b710245161a05ca95e924aae65464d626e015126..b97f7fb8f26a3439db248b2769de1f9d6088fa26 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
@@ -232,13 +232,37 @@ class KernelCascadeExpression extends Let implements KernelExpression {
}
}
+/// Concrete shadow object representing a complex assignment in kernel form.
ahe 2017/06/08 14:16:33 What is a complex assignment?
Paul Berry 2017/06/08 16:17:04 I'm still figuring out exactly where to draw the l
+class KernelComplexAssign extends Let implements KernelExpression {
+ KernelComplexAssign(VariableDeclaration variable, Expression body)
+ : super(variable, body);
+
+ @override
+ void _collectDependencies(KernelDependencyCollector collector) {
+ // Assignment expressions are not immediately evident expressions.
+ collector.recordNotImmediatelyEvident(fileOffset);
+ }
+
+ @override
+ DartType _inferExpression(
+ KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
+ return inferrer.inferIndexAssign(this, typeContext, typeNeeded);
+ }
+}
+
/// Concrete shadow object representing a conditional expression in kernel form.
/// Shadow object for [ConditionalExpression].
class KernelConditionalExpression extends ConditionalExpression
implements KernelExpression {
+ /// Indicates whether this conditional expression is associated with a `??=`
+ /// in a null-aware compound assignment.
+ final bool _isNullAwareCombiner;
+
KernelConditionalExpression(
- Expression condition, Expression then, Expression otherwise)
- : super(condition, then, otherwise, const DynamicType());
+ Expression condition, Expression then, Expression otherwise,
+ {bool isNullAwareCombiner: false})
+ : _isNullAwareCombiner = isNullAwareCombiner,
+ super(condition, then, otherwise, const DynamicType());
@override
void _collectDependencies(KernelDependencyCollector collector) {
@@ -268,6 +292,11 @@ class KernelConditionalExpression extends ConditionalExpression
inferrer.listener.conditionalExpressionExit(this, inferredType);
return inferredType;
}
+
+ /// Helper method allowing [_isNullAwareCombiner] to be checked from outside
+ /// this library without adding a public member to the class.
+ static bool isNullAwareCombiner(KernelConditionalExpression e) =>
+ e._isNullAwareCombiner;
}
/// Shadow object for [ConstructorInvocation].
@@ -1038,9 +1067,16 @@ class KernelMethodInvocation extends MethodInvocation
/// resulting from the invocation of a function expression.
final bool _isImplicitCall;
+ /// Indicates whether this method invocation invokes the operator that
+ /// combines old and new values in a compound assignment.
+ final bool _isCombiner;
+
KernelMethodInvocation(Expression receiver, Name name, Arguments arguments,
- {bool isImplicitCall: false, Procedure interfaceTarget})
+ {bool isImplicitCall: false,
+ Procedure interfaceTarget,
+ bool isCombiner: false})
: _isImplicitCall = isImplicitCall,
+ _isCombiner = isCombiner,
super(receiver, name, arguments, interfaceTarget);
@override
@@ -1053,34 +1089,19 @@ class KernelMethodInvocation extends MethodInvocation
@override
DartType _inferExpression(
KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
+ if (identical(name.name, '[]=')) {
+ return inferrer.inferIndexAssign(this, typeContext, 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;
- if (receiverType is InterfaceType) {
- interfaceMember = inferrer.classHierarchy
- .getInterfaceMember(receiverType.classNode, name);
- // Our non-strong golden files currently don't include interface
- // targets, so we can't store the interface target without causing tests
- // to fail. TODO(paulberry): fix this.
- if (inferrer.strongMode) {
- if (interfaceMember != null) {
- inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset,
- 'target', new InstrumentationValueForMember(interfaceMember));
- }
- // interfaceTarget is currently required to be a procedure, so we skip
- // if it's anything else. TODO(paulberry): fix this - see
- // https://codereview.chromium.org/2923653003/.
- if (interfaceMember is Procedure) {
- interfaceTarget = interfaceMember;
- }
- }
- if (interfaceMember is Procedure) {
- isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment
- .isOverloadedArithmeticOperator(interfaceMember);
- }
+ Member interfaceMember =
+ inferrer.findMethodInvocationMember(receiverType, this);
+ if (interfaceMember is Procedure) {
+ isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment
+ .isOverloadedArithmeticOperator(interfaceMember);
}
var calleeType = inferrer.getCalleeFunctionType(
interfaceMember, receiverType, name, !_isImplicitCall);
@@ -1091,6 +1112,10 @@ class KernelMethodInvocation extends MethodInvocation
inferrer.listener.methodInvocationExit(this, inferredType);
return inferredType;
}
+
+ /// Helper method allowing [_isCombiner] to be checked from outside this
+ /// library without adding a public member to the class.
+ static bool isCombiner(KernelMethodInvocation e) => e._isCombiner;
}
/// Shadow object for [Not].
@@ -1163,27 +1188,17 @@ class KernelPropertyGet extends PropertyGet implements KernelExpression {
inferrer.listener.propertyGetEnter(this, typeContext) || typeNeeded;
// First infer the receiver so we can look up the getter that was invoked.
var receiverType = inferrer.inferExpression(receiver, null, true);
- Member interfaceMember;
- if (receiverType is InterfaceType) {
- interfaceMember = inferrer.classHierarchy
- .getInterfaceMember(receiverType.classNode, name);
- if (inferrer.isTopLevel &&
- ((interfaceMember is Procedure &&
- interfaceMember.kind == ProcedureKind.Getter) ||
- interfaceMember is Field)) {
- // References to fields and getters can't be relied upon for top level
- // inference.
- inferrer.recordNotImmediatelyEvident(fileOffset);
- }
- // Our non-strong golden files currently don't include interface targets,
- // so we can't store the interface target without causing tests to fail.
- // TODO(paulberry): fix this.
- if (inferrer.strongMode) {
- inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset,
- 'target', new InstrumentationValueForMember(interfaceMember));
- interfaceTarget = interfaceMember;
- }
+ Member interfaceMember =
+ inferrer.findInterfaceMember(receiverType, name, fileOffset);
+ if (inferrer.isTopLevel &&
+ ((interfaceMember is Procedure &&
+ interfaceMember.kind == ProcedureKind.Getter) ||
+ interfaceMember is Field)) {
+ // References to fields and getters can't be relied upon for top level
+ // inference.
+ inferrer.recordNotImmediatelyEvident(fileOffset);
}
+ interfaceTarget = interfaceMember;
var inferredType =
inferrer.getCalleeType(interfaceMember, receiverType, name);
// TODO(paulberry): Infer tear-off type arguments if appropriate.
@@ -1215,19 +1230,9 @@ class KernelPropertySet extends PropertySet implements KernelExpression {
inferrer.listener.propertySetEnter(this, typeContext) || typeNeeded;
// First infer the receiver so we can look up the setter that was invoked.
var receiverType = inferrer.inferExpression(receiver, null, true);
- Member interfaceMember;
- if (receiverType is InterfaceType) {
- interfaceMember = inferrer.classHierarchy
- .getInterfaceMember(receiverType.classNode, name, setter: true);
- // Our non-strong golden files currently don't include interface targets,
- // so we can't store the interface target without causing tests to fail.
- // TODO(paulberry): fix this.
- if (inferrer.strongMode) {
- inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset,
- 'target', new InstrumentationValueForMember(interfaceMember));
- interfaceTarget = interfaceMember;
- }
- }
+ Member interfaceMember = inferrer
+ .findInterfaceMember(receiverType, name, fileOffset, setter: true);
+ interfaceTarget = interfaceMember;
var setterType = inferrer.getSetterType(interfaceMember, receiverType);
var inferredType = inferrer.inferExpression(value, setterType, typeNeeded);
inferrer.listener.propertySetExit(this, inferredType);
@@ -1797,6 +1802,10 @@ class KernelVariableDeclaration extends VariableDeclaration
final bool _isLocalFunction;
+ /// Indicates whether this variable declaration exists for the sole purpose of
+ /// discarding a return value in a complex desugared expression.
+ final bool _isDiscarding;
ahe 2017/06/08 14:16:33 It would be easier for for me to understand the me
Paul Berry 2017/06/08 16:17:04 I'm open to changing this, but I think "voidContex
+
KernelVariableDeclaration(String name, this._functionNestingLevel,
{Expression initializer,
DartType type,
@@ -1805,6 +1814,7 @@ class KernelVariableDeclaration extends VariableDeclaration
bool isLocalFunction: false})
: _implicitlyTyped = type == null,
_isLocalFunction = isLocalFunction,
+ _isDiscarding = false,
super(name,
initializer: initializer,
type: type ?? const DynamicType(),
@@ -1812,9 +1822,11 @@ class KernelVariableDeclaration extends VariableDeclaration
isConst: isConst);
KernelVariableDeclaration.forValue(
- Expression initializer, this._functionNestingLevel)
+ Expression initializer, this._functionNestingLevel,
+ {bool isDiscarding: false})
: _implicitlyTyped = true,
_isLocalFunction = false,
+ _isDiscarding = isDiscarding,
super.forValue(initializer);
@override
@@ -1833,6 +1845,11 @@ class KernelVariableDeclaration extends VariableDeclaration
inferrer.listener.variableDeclarationExit(this);
}
+ /// Helper method allowing [_isDiscarding] to be checked from outside this
+ /// library without adding a public member to the class.
+ static bool isDiscarding(VariableDeclaration v) =>
+ v is KernelVariableDeclaration && v._isDiscarding;
+
/// Determine whether the given [KernelVariableDeclaration] had an implicit
/// type.
///

Powered by Google App Engine
This is Rietveld 408576698