anchor.diff:      flow = FlowAnalysis<_Statement, _Expression, _Var, _Type>(this, this, this);
     }
   
  +  _Var addAssignedVar(String name, String type) {
  +    var v = _Var(name, _Type(type));
  +    flow.add(v, assigned: true);
  +    return v;
  +  }
  +
     @override
     bool isLocalVariable(_Var variable) {
       throw UnimplementedError('TODO(paulberry)');
  
positive.code:       'int <: String': false,
        'int? <: int': false,
        'String <: int': false,
      };
  
      if (leftType.type == rightType.type) return true;
  
negative.code: main() {
    group('API', () {
      test('conditionNotEqNull promotes true branch', () {
        var h = _Harness();
        var x = h.addAssignedVar('x', 'int?');
        var expr = _Expression();
        h.flow.conditionNotEqNull(expr, x);
        h.flow.ifStatement_thenBegin(expr);
        expect(h.flow.promotedType(x).type, 'int');
        h.flow.ifStatement_elseBegin();
        expect(h.flow.promotedType(x), isNull);
        h.flow.ifStatement_end(true);
        h.flow.verifyStackEmpty();
      });
  
      test('conditionEqNull promotes false branch', () {
        var h = _Harness();
        var x = h.addAssignedVar('x', 'int?');
        var expr = _Expression();
        h.flow.conditionEqNull(expr, x);
        h.flow.ifStatement_thenBegin(expr);
        expect(h.flow.promotedType(x), isNull);
        h.flow.ifStatement_elseBegin();
        expect(h.flow.promotedType(x).type, 'int');
        h.flow.ifStatement_end(true);
        h.flow.verifyStackEmpty();
      });
  
      test('ifStatement_end(false) keeps else branch if then branch exits', () {
        var h = _Harness();
        var x = h.addAssignedVar('x', 'int?');
        var expr = _Expression();
        h.flow.conditionEqNull(expr, x);
        h.flow.ifStatement_thenBegin(expr);
        h.flow.handleExit();
        h.flow.ifStatement_end(false);
        expect(h.flow.promotedType(x).type, 'int');
        h.flow.verifyStackEmpty();
      });
  
      void _checkIs(String declaredType, String tryPromoteType,
          String expectedPromotedType) {
        var h = _Harness();
        var x = h.addAssignedVar('x', 'int?');
        var expr = _Expression();
        h.flow.isExpression_end(expr, x, false, _Type(tryPromoteType));
        h.flow.ifStatement_thenBegin(expr);
        if (expectedPromotedType == null) {
          expect(h.flow.promotedType(x), isNull);
        } else {
          expect(h.flow.promotedType(x).type, 'int');
        }
        h.flow.ifStatement_elseBegin();
        expect(h.flow.promotedType(x), isNull);
        h.flow.ifStatement_end(true);
        h.flow.verifyStackEmpty();
      }
  
      test('isExpression_end promotes to a subtype', () {
  