| Index: pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
|
| diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
|
| index fa961f2390b2c1879b8fd53e5cd7be2488b84228..3314fcdc308d712e688d8c76ee43aebfc308ae1f 100644
|
| --- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
|
| @@ -115,8 +115,12 @@ abstract class TypeSystem<T> {
|
| /**
|
| * Returns a new receiver type for this [selector] applied to
|
| * [receiverType].
|
| + *
|
| + * The option [isConditional] is true when [selector] was seen in a
|
| + * conditional send (e.g. `a?.selector`), in which case the returned type may
|
| + * be null.
|
| */
|
| - T refineReceiver(Selector selector, T receiverType);
|
| + T refineReceiver(Selector selector, T receiverType, bool isConditional);
|
|
|
| /**
|
| * Returns the internal inferrer representation for [mask].
|
| @@ -441,6 +445,13 @@ class LocalsHandler<T> {
|
| }
|
| updateLocal() {
|
| T currentType = locals[local];
|
| +
|
| + SendSet send = node != null ? node.asSendSet() : null;
|
| + if (send != null && send.isIfNullAssignment && currentType != null) {
|
| + // If-null assignments may return either the new or the original value.
|
| + type = types.addPhiInput(
|
| + local, types.allocatePhi(locals.block, local, currentType), type);
|
| + }
|
| locals[local] = type;
|
| if (currentType != type) {
|
| inferrer.recordLocalUpdate(local, type);
|
| @@ -988,6 +999,16 @@ abstract class InferrerVisitor
|
| }
|
|
|
| @override
|
| + T visitIfNotNullDynamicPropertyInvoke(
|
| + Send node,
|
| + Node receiver,
|
| + NodeList arguments,
|
| + Selector selector,
|
| + _) {
|
| + return handleDynamicInvoke(node);
|
| + }
|
| +
|
| + @override
|
| T visitThisPropertyInvoke(
|
| Send node,
|
| NodeList arguments,
|
| @@ -997,6 +1018,13 @@ abstract class InferrerVisitor
|
| }
|
|
|
| @override
|
| + T visitIfNull(Send node, Node left, Node right, _) {
|
| + T firstType = visit(left);
|
| + T secondType = visit(right);
|
| + return types.allocateDiamondPhi(firstType, secondType);
|
| + }
|
| +
|
| + @override
|
| T visitLogicalAnd(Send node, Node left, Node right, _) {
|
| conditionIsSimple = false;
|
| bool oldAccumulateIsChecks = accumulateIsChecks;
|
|
|