| 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 ffe96b4795fae15b7a22e64c830215b2ab565621..003251fe38a3219a5632950b0ac1f085e5051468 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
|
| @@ -1418,6 +1418,36 @@ class KernelNot extends Not implements KernelExpression {
|
| }
|
| }
|
|
|
| +/// 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
|
| +/// expression:
|
| +///
|
| +/// let v = a in v == null ? null : v.b
|
| +class KernelNullAwarePropertyGet extends Let implements KernelExpression {
|
| + KernelNullAwarePropertyGet(
|
| + VariableDeclaration variable, ConditionalExpression body)
|
| + : super(variable, body);
|
| +
|
| + @override
|
| + ConditionalExpression get body => super.body;
|
| +
|
| + PropertyGet get _desugaredGet => 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) {
|
| + return inferrer.inferPropertyGet(this, variable.initializer, fileOffset,
|
| + _desugaredGet, typeContext, typeNeeded);
|
| + }
|
| +}
|
| +
|
| /// Concrete shadow object representing a null literal in kernel form.
|
| class KernelNullLiteral extends NullLiteral implements KernelExpression {
|
| @override
|
| @@ -1558,34 +1588,8 @@ class KernelPropertyGet extends PropertyGet implements KernelExpression {
|
| @override
|
| DartType _inferExpression(
|
| KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
|
| - typeNeeded =
|
| - 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 =
|
| - inferrer.findInterfaceMember(receiverType, name, fileOffset);
|
| - if (inferrer.isTopLevel &&
|
| - ((interfaceMember is Procedure &&
|
| - interfaceMember.kind == ProcedureKind.Getter) ||
|
| - interfaceMember is Field)) {
|
| - if (TypeInferenceEngineImpl.fullTopLevelInference) {
|
| - if (interfaceMember is KernelField &&
|
| - interfaceMember._fieldNode != null) {
|
| - inferrer.engine
|
| - .inferFieldFused(interfaceMember._fieldNode, inferrer.fieldNode);
|
| - }
|
| - } else {
|
| - // 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.
|
| - inferrer.listener.propertyGetExit(this, inferredType);
|
| - return typeNeeded ? inferredType : null;
|
| + return inferrer.inferPropertyGet(
|
| + this, receiver, fileOffset, this, typeContext, typeNeeded);
|
| }
|
| }
|
|
|
|
|