diff --git a/lib/src/checker/checker.dart b/lib/src/checker/checker.dart
index 0af5675..10bae9c 100644
--- a/lib/src/checker/checker.dart
+++ b/lib/src/checker/checker.dart
@@ -4,945 +4,4 @@
 
 library dev_compiler.src.checker.checker;
 
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
-
-import '../info.dart';
-import '../utils.dart' show getMemberType;
-import 'rules.dart';
-
-/// Checks for overriding declarations of fields and methods. This is used to
-/// check overrides between classes and superclasses, interfaces, and mixin
-/// applications.
-class _OverrideChecker {
-  bool _failure = false;
-  final TypeRules _rules;
-  final AnalysisErrorListener _reporter;
-
-  _OverrideChecker(this._rules, this._reporter);
-
-  void check(ClassDeclaration node) {
-    if (node.element.type.isObject) return;
-    _checkSuperOverrides(node);
-    _checkMixinApplicationOverrides(node);
-    _checkAllInterfaceOverrides(node);
-  }
-
-  /// Check overrides from mixin applications themselves. For example, in:
-  ///
-  ///      A extends B with E, F
-  ///
-  ///  we check:
-  ///
-  ///      B & E against B (equivalently how E overrides B)
-  ///      B & E & F against B & E (equivalently how F overrides both B and E)
-  void _checkMixinApplicationOverrides(ClassDeclaration node) {
-    var type = node.element.type;
-    var parent = type.superclass;
-    var mixins = type.mixins;
-
-    // Check overrides from applying mixins
-    for (int i = 0; i < mixins.length; i++) {
-      var seen = new Set<String>();
-      var current = mixins[i];
-      var errorLocation = node.withClause.mixinTypes[i];
-      for (int j = i - 1; j >= 0; j--) {
-        _checkIndividualOverridesFromType(
-            current, mixins[j], errorLocation, seen);
-      }
-      _checkIndividualOverridesFromType(current, parent, errorLocation, seen);
-    }
-  }
-
-  /// Check overrides between a class and its superclasses and mixins. For
-  /// example, in:
-  ///
-  ///      A extends B with E, F
-  ///
-  /// we check A against B, B super classes, E, and F.
-  ///
-  /// Internally we avoid reporting errors twice and we visit classes bottom up
-  /// to ensure we report the most immediate invalid override first. For
-  /// example, in the following code we'll report that `Test` has an invalid
-  /// override with respect to `Parent` (as opposed to an invalid override with
-  /// respect to `Grandparent`):
-  ///
-  ///     class Grandparent {
-  ///         m(A a) {}
-  ///     }
-  ///     class Parent extends Grandparent {
-  ///         m(A a) {}
-  ///     }
-  ///     class Test extends Parent {
-  ///         m(B a) {} // invalid override
-  ///     }
-  void _checkSuperOverrides(ClassDeclaration node) {
-    var seen = new Set<String>();
-    var current = node.element.type;
-    var visited = new Set<InterfaceType>();
-    do {
-      visited.add(current);
-      current.mixins.reversed
-          .forEach((m) => _checkIndividualOverridesFromClass(node, m, seen));
-      _checkIndividualOverridesFromClass(node, current.superclass, seen);
-      current = current.superclass;
-    } while (!current.isObject && !visited.contains(current));
-  }
-
-  /// Checks that implementations correctly override all reachable interfaces.
-  /// In particular, we need to check these overrides for the definitions in
-  /// the class itself and each its superclasses. If a superclass is not
-  /// abstract, then we can skip its transitive interfaces. For example, in:
-  ///
-  ///     B extends C implements G
-  ///     A extends B with E, F implements H, I
-  ///
-  /// we check:
-  ///
-  ///     C against G, H, and I
-  ///     B against G, H, and I
-  ///     E against H and I // no check against G because B is a concrete class
-  ///     F against H and I
-  ///     A against H and I
-  void _checkAllInterfaceOverrides(ClassDeclaration node) {
-    var seen = new Set<String>();
-    // Helper function to collect all reachable interfaces.
-    find(InterfaceType interfaceType, Set result) {
-      if (interfaceType == null || interfaceType.isObject) return;
-      if (result.contains(interfaceType)) return;
-      result.add(interfaceType);
-      find(interfaceType.superclass, result);
-      interfaceType.mixins.forEach((i) => find(i, result));
-      interfaceType.interfaces.forEach((i) => find(i, result));
-    }
-
-    // Check all interfaces reachable from the `implements` clause in the
-    // current class against definitions here and in superclasses.
-    var localInterfaces = new Set<InterfaceType>();
-    var type = node.element.type;
-    type.interfaces.forEach((i) => find(i, localInterfaces));
-    _checkInterfacesOverrides(node, localInterfaces, seen,
-        includeParents: true);
-
-    // Check also how we override locally the interfaces from parent classes if
-    // the parent class is abstract. Otherwise, these will be checked as
-    // overrides on the concrete superclass.
-    var superInterfaces = new Set<InterfaceType>();
-    var parent = type.superclass;
-    // TODO(sigmund): we don't seem to be reporting the analyzer error that a
-    // non-abstract class is not implementing an interface. See
-    // https://github.com/dart-lang/dart-dev-compiler/issues/25
-    while (parent != null && parent.element.isAbstract) {
-      parent.interfaces.forEach((i) => find(i, superInterfaces));
-      parent = parent.superclass;
-    }
-    _checkInterfacesOverrides(node, superInterfaces, seen,
-        includeParents: false);
-  }
-
-  /// Checks that [cls] and its super classes (including mixins) correctly
-  /// overrides each interface in [interfaces]. If [includeParents] is false,
-  /// then mixins are still checked, but the base type and it's transitive
-  /// supertypes are not.
-  ///
-  /// [cls] can be either a [ClassDeclaration] or a [InterfaceType]. For
-  /// [ClassDeclaration]s errors are reported on the member that contains the
-  /// invalid override, for [InterfaceType]s we use [errorLocation] instead.
-  void _checkInterfacesOverrides(
-      cls, Iterable<InterfaceType> interfaces, Set<String> seen,
-      {Set<InterfaceType> visited,
-      bool includeParents: true,
-      AstNode errorLocation}) {
-    var node = cls is ClassDeclaration ? cls : null;
-    var type = cls is InterfaceType ? cls : node.element.type;
-
-    if (visited == null) {
-      visited = new Set<InterfaceType>();
-    } else if (visited.contains(type)) {
-      // Malformed type.
-      return;
-    } else {
-      visited.add(type);
-    }
-
-    // Check direct overrides on [type]
-    for (var interfaceType in interfaces) {
-      if (node != null) {
-        _checkIndividualOverridesFromClass(node, interfaceType, seen);
-      } else {
-        _checkIndividualOverridesFromType(
-            type, interfaceType, errorLocation, seen);
-      }
-    }
-
-    // Check overrides from its mixins
-    for (int i = 0; i < type.mixins.length; i++) {
-      var loc =
-          errorLocation != null ? errorLocation : node.withClause.mixinTypes[i];
-      for (var interfaceType in interfaces) {
-        // We copy [seen] so we can report separately if more than one mixin or
-        // the base class have an invalid override.
-        _checkIndividualOverridesFromType(
-            type.mixins[i], interfaceType, loc, new Set.from(seen));
-      }
-    }
-
-    // Check overrides from its superclasses
-    if (includeParents) {
-      var parent = type.superclass;
-      if (parent.isObject) return;
-      var loc = errorLocation != null ? errorLocation : node.extendsClause;
-      // No need to copy [seen] here because we made copies above when reporting
-      // errors on mixins.
-      _checkInterfacesOverrides(parent, interfaces, seen,
-          visited: visited, includeParents: true, errorLocation: loc);
-    }
-  }
-
-  /// Check that individual methods and fields in [subType] correctly override
-  /// the declarations in [baseType].
-  ///
-  /// The [errorLocation] node indicates where errors are reported, see
-  /// [_checkSingleOverride] for more details.
-  ///
-  /// The set [seen] is used to avoid reporting overrides more than once. It
-  /// is used when invoking this function multiple times when checking several
-  /// types in a class hierarchy. Errors are reported only the first time an
-  /// invalid override involving a specific member is encountered.
-  _checkIndividualOverridesFromType(InterfaceType subType,
-      InterfaceType baseType, AstNode errorLocation, Set<String> seen) {
-    void checkHelper(ExecutableElement e) {
-      if (e.isStatic) return;
-      if (seen.contains(e.name)) return;
-      if (_checkSingleOverride(e, baseType, null, errorLocation)) {
-        seen.add(e.name);
-      }
-    }
-    subType.methods.forEach(checkHelper);
-    subType.accessors.forEach(checkHelper);
-  }
-
-  /// Check that individual methods and fields in [subType] correctly override
-  /// the declarations in [baseType].
-  ///
-  /// The [errorLocation] node indicates where errors are reported, see
-  /// [_checkSingleOverride] for more details.
-  _checkIndividualOverridesFromClass(
-      ClassDeclaration node, InterfaceType baseType, Set<String> seen) {
-    for (var member in node.members) {
-      if (member is ConstructorDeclaration) continue;
-      if (member is FieldDeclaration) {
-        if (member.isStatic) continue;
-        for (var variable in member.fields.variables) {
-          var element = variable.element as PropertyInducingElement;
-          var name = element.name;
-          if (seen.contains(name)) continue;
-          var getter = element.getter;
-          var setter = element.setter;
-          bool found = _checkSingleOverride(getter, baseType, variable, member);
-          if (!variable.isFinal &&
-              !variable.isConst &&
-              _checkSingleOverride(setter, baseType, variable, member)) {
-            found = true;
-          }
-          if (found) seen.add(name);
-        }
-      } else {
-        if ((member as MethodDeclaration).isStatic) continue;
-        var method = (member as MethodDeclaration).element;
-        if (seen.contains(method.name)) continue;
-        if (_checkSingleOverride(method, baseType, member, member)) {
-          seen.add(method.name);
-        }
-      }
-    }
-  }
-
-  /// Checks that [element] correctly overrides its corresponding member in
-  /// [type]. Returns `true` if an override was found, that is, if [element] has
-  /// a corresponding member in [type] that it overrides.
-  ///
-  /// The [errorLocation] is a node where the error is reported. For example, a
-  /// bad override of a method in a class with respect to its superclass is
-  /// reported directly at the method declaration. However, invalid overrides
-  /// from base classes to interfaces, mixins to the base they are applied to,
-  /// or mixins to interfaces are reported at the class declaration, since the
-  /// base class or members on their own were not incorrect, only combining them
-  /// with the interface was problematic. For example, these are example error
-  /// locations in these cases:
-  ///
-  ///     error: base class introduces an invalid override. The type of B.foo is
-  ///     not a subtype of E.foo:
-  ///       class A extends B implements E { ... }
-  ///               ^^^^^^^^^
-  ///
-  ///     error: mixin introduces an invalid override. The type of C.foo is not
-  ///     a subtype of E.foo:
-  ///       class A extends B with C implements E { ... }
-  ///                              ^
-  ///
-  /// When checking for overrides from a type and it's super types, [node] is
-  /// the AST node that defines [element]. This is used to determine whether the
-  /// type of the element could be inferred from the types in the super classes.
-  bool _checkSingleOverride(ExecutableElement element, InterfaceType type,
-      AstNode node, AstNode errorLocation) {
-    assert(!element.isStatic);
-
-    FunctionType subType = _rules.elementType(element);
-    // TODO(vsm): Test for generic
-    FunctionType baseType = getMemberType(type, element);
-
-    if (baseType == null) return false;
-    if (!_rules.isAssignable(subType, baseType)) {
-      // See whether non-assignable cases fit one of our common patterns:
-      //
-      // Common pattern 1: Inferable return type (on getters and methods)
-      //   class A {
-      //     int get foo => ...;
-      //     String toString() { ... }
-      //   }
-      //   class B extends A {
-      //     get foo => e; // no type specified.
-      //     toString() { ... } // no return type specified.
-      //   }
-      _recordMessage(new InvalidMethodOverride(
-          errorLocation, element, type, subType, baseType));
-    }
-    return true;
-  }
-
-  void _recordMessage(StaticInfo info) {
-    if (info == null) return;
-    var error = info.toAnalysisError();
-    if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true;
-    _reporter.onError(error);
-  }
-}
-
-/// Checks the body of functions and properties.
-class CodeChecker extends RecursiveAstVisitor {
-  final TypeRules rules;
-  final AnalysisErrorListener reporter;
-  final _OverrideChecker _overrideChecker;
-  bool _failure = false;
-  bool get failure => _failure || _overrideChecker._failure;
-
-  void reset() {
-    _failure = false;
-    _overrideChecker._failure = false;
-  }
-
-  CodeChecker(TypeRules rules, AnalysisErrorListener reporter)
-      : rules = rules,
-        reporter = reporter,
-        _overrideChecker = new _OverrideChecker(rules, reporter);
-
-  @override
-  void visitComment(Comment node) {
-    // skip, no need to do typechecking inside comments (they may contain
-    // comment references which would require resolution).
-  }
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    _overrideChecker.check(node);
-    super.visitClassDeclaration(node);
-  }
-
-  @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    var token = node.operator;
-    if (token.type != TokenType.EQ) {
-      _checkCompoundAssignment(node);
-    } else {
-      DartType staticType = _getStaticType(node.leftHandSide);
-      checkAssignment(node.rightHandSide, staticType);
-    }
-    node.visitChildren(this);
-  }
-
-  /// Check constructor declaration to ensure correct super call placement.
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    node.visitChildren(this);
-
-    final init = node.initializers;
-    for (int i = 0, last = init.length - 1; i < last; i++) {
-      final node = init[i];
-      if (node is SuperConstructorInvocation) {
-        _recordMessage(new InvalidSuperInvocation(node));
-      }
-    }
-  }
-
-  @override
-  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    var field = node.fieldName;
-    var element = field.staticElement;
-    DartType staticType = rules.elementType(element);
-    checkAssignment(node.expression, staticType);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitForEachStatement(ForEachStatement node) {
-    // Check that the expression is an Iterable.
-    var expr = node.iterable;
-    var iterableType = node.awaitKeyword != null
-        ? rules.provider.streamType
-        : rules.provider.iterableType;
-    var loopVariable = node.identifier != null
-        ? node.identifier
-        : node.loopVariable?.identifier;
-    if (loopVariable != null) {
-      var iteratorType = loopVariable.staticType;
-      var checkedType = iterableType.substitute4([iteratorType]);
-      checkAssignment(expr, checkedType);
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitForStatement(ForStatement node) {
-    if (node.condition != null) {
-      checkBoolean(node.condition);
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitIfStatement(IfStatement node) {
-    checkBoolean(node.condition);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitDoStatement(DoStatement node) {
-    checkBoolean(node.condition);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitWhileStatement(WhileStatement node) {
-    checkBoolean(node.condition);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitSwitchStatement(SwitchStatement node) {
-    // SwitchStatement defines a boolean conversion to check the result of the
-    // case value == the switch value, but in dev_compiler we require a boolean
-    // return type from an overridden == operator (because Object.==), so
-    // checking in SwitchStatement shouldn't be necessary.
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitListLiteral(ListLiteral node) {
-    var type = rules.provider.dynamicType;
-    if (node.typeArguments != null) {
-      var targs = node.typeArguments.arguments;
-      if (targs.length > 0) type = targs[0].type;
-    }
-    var elements = node.elements;
-    for (int i = 0; i < elements.length; i++) {
-      checkArgument(elements[i], type);
-    }
-    super.visitListLiteral(node);
-  }
-
-  @override
-  void visitMapLiteral(MapLiteral node) {
-    var ktype = rules.provider.dynamicType;
-    var vtype = rules.provider.dynamicType;
-    if (node.typeArguments != null) {
-      var targs = node.typeArguments.arguments;
-      if (targs.length > 0) ktype = targs[0].type;
-      if (targs.length > 1) vtype = targs[1].type;
-    }
-    var entries = node.entries;
-    for (int i = 0; i < entries.length; i++) {
-      var entry = entries[i];
-      checkArgument(entry.key, ktype);
-      checkArgument(entry.value, vtype);
-    }
-    super.visitMapLiteral(node);
-  }
-
-  // Check invocations
-  void checkArgumentList(ArgumentList node, FunctionType type) {
-    NodeList<Expression> list = node.arguments;
-    int len = list.length;
-    for (int i = 0; i < len; ++i) {
-      Expression arg = list[i];
-      ParameterElement element = arg.staticParameterElement;
-      if (element == null) {
-        if (type.parameters.length < len) {
-          // We found an argument mismatch, the analyzer will report this too,
-          // so no need to insert an error for this here.
-          continue;
-        }
-        element = type.parameters[i];
-        // TODO(vsm): When can this happen?
-        assert(element != null);
-      }
-      DartType expectedType = rules.elementType(element);
-      if (expectedType == null) expectedType = rules.provider.dynamicType;
-      checkArgument(arg, expectedType);
-    }
-  }
-
-  void checkArgument(Expression arg, DartType expectedType) {
-    // Preserve named argument structure, so their immediate parent is the
-    // method invocation.
-    if (arg is NamedExpression) {
-      arg = (arg as NamedExpression).expression;
-    }
-    checkAssignment(arg, expectedType);
-  }
-
-  void checkFunctionApplication(
-      Expression node, Expression f, ArgumentList list) {
-    if (rules.isDynamicCall(f)) {
-      // If f is Function and this is a method invocation, we should have
-      // gotten an analyzer error, so no need to issue another error.
-      _recordDynamicInvoke(node, f);
-    } else {
-      checkArgumentList(list, rules.getTypeAsCaller(f));
-    }
-  }
-
-  @override
-  visitMethodInvocation(MethodInvocation node) {
-    var target = node.realTarget;
-    if (rules.isDynamicTarget(target) &&
-        !_isObjectMethod(node, node.methodName)) {
-      _recordDynamicInvoke(node, target);
-
-      // Mark the tear-off as being dynamic, too. This lets us distinguish
-      // cases like:
-      //
-      //     dynamic d;
-      //     d.someMethod(...); // the whole method call must be a dynamic send.
-      //
-      // ... from case like:
-      //
-      //     SomeType s;
-      //     s.someDynamicField(...); // static get, followed by dynamic call.
-      //
-      // The first case is handled here, the second case is handled below when
-      // we call [checkFunctionApplication].
-      DynamicInvoke.set(node.methodName, true);
-    } else {
-      checkFunctionApplication(node, node.methodName, node.argumentList);
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    checkFunctionApplication(node, node.function, node.argumentList);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    var type = node.staticElement.type;
-    checkArgumentList(node.argumentList, type);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    var element = node.staticElement;
-    if (element == null) {
-      _recordMessage(new MissingTypeError(node));
-    } else {
-      var type = node.staticElement.type;
-      checkArgumentList(node.argumentList, type);
-    }
-    node.visitChildren(this);
-  }
-
-  void _checkReturnOrYield(Expression expression, AstNode node,
-      {bool yieldStar: false}) {
-    var body = node.getAncestor((n) => n is FunctionBody);
-    var type = rules.getExpectedReturnType(body, yieldStar: yieldStar);
-    if (type == null) {
-      // We have a type mismatch: the async/async*/sync* modifier does
-      // not match the return or yield type.  We should have already gotten an
-      // analyzer error in this case.
-      return;
-    }
-    // TODO(vsm): Enforce void or dynamic (to void?) when expression is null.
-    if (expression != null) checkAssignment(expression, type);
-  }
-
-  @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    _checkReturnOrYield(node.expression, node);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitReturnStatement(ReturnStatement node) {
-    _checkReturnOrYield(node.expression, node);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitYieldStatement(YieldStatement node) {
-    _checkReturnOrYield(node.expression, node, yieldStar: node.star != null);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitPropertyAccess(PropertyAccess node) {
-    var target = node.realTarget;
-    if (rules.isDynamicTarget(target) &&
-        !_isObjectProperty(target, node.propertyName)) {
-      _recordDynamicInvoke(node, target);
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    final target = node.prefix;
-    if (rules.isDynamicTarget(target) &&
-        !_isObjectProperty(target, node.identifier)) {
-      _recordDynamicInvoke(node, target);
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    // Check that defaults have the proper subtype.
-    var parameter = node.parameter;
-    var parameterType = rules.elementType(parameter.element);
-    assert(parameterType != null);
-    var defaultValue = node.defaultValue;
-    if (defaultValue != null) {
-      checkAssignment(defaultValue, parameterType);
-    }
-
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitFieldFormalParameter(FieldFormalParameter node) {
-    var element = node.element;
-    var typeName = node.type;
-    if (typeName != null) {
-      var type = rules.elementType(element);
-      var fieldElement =
-          node.identifier.staticElement as FieldFormalParameterElement;
-      var fieldType = rules.elementType(fieldElement.field);
-      if (!rules.isSubTypeOf(type, fieldType)) {
-        var staticInfo =
-            new InvalidParameterDeclaration(rules, node, fieldType);
-        _recordMessage(staticInfo);
-      }
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    var arguments = node.argumentList;
-    var element = node.staticElement;
-    if (element != null) {
-      var type = rules.elementType(node.staticElement);
-      checkArgumentList(arguments, type);
-    } else {
-      _recordMessage(new MissingTypeError(node));
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    TypeName type = node.type;
-    if (type == null) {
-      // No checks are needed when the type is var. Although internally the
-      // typing rules may have inferred a more precise type for the variable
-      // based on the initializer.
-    } else {
-      var dartType = getType(type);
-      for (VariableDeclaration variable in node.variables) {
-        var initializer = variable.initializer;
-        if (initializer != null) {
-          checkAssignment(initializer, dartType);
-        }
-      }
-    }
-    node.visitChildren(this);
-  }
-
-  void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) {
-    var type = getType(typeName);
-    if (!rules.isGroundType(type)) {
-      _recordMessage(new NonGroundTypeCheckInfo(node, type));
-    }
-  }
-
-  @override
-  void visitAsExpression(AsExpression node) {
-    // We could do the same check as the IsExpression below, but that is
-    // potentially too conservative.  Instead, at runtime, we must fail hard
-    // if the Dart as and the DDC as would return different values.
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitIsExpression(IsExpression node) {
-    _checkRuntimeTypeCheck(node, node.type);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitPrefixExpression(PrefixExpression node) {
-    if (node.operator.type == TokenType.BANG) {
-      checkBoolean(node.operand);
-    } else {
-      _checkUnary(node);
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitPostfixExpression(PostfixExpression node) {
-    _checkUnary(node);
-    node.visitChildren(this);
-  }
-
-  void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
-    var op = node.operator;
-    if (op.isUserDefinableOperator ||
-        op.type == TokenType.PLUS_PLUS ||
-        op.type == TokenType.MINUS_MINUS) {
-      if (rules.isDynamicTarget(node.operand)) {
-        _recordDynamicInvoke(node, node.operand);
-      }
-      // For ++ and --, even if it is not dynamic, we still need to check
-      // that the user defined method accepts an `int` as the RHS.
-      // We assume Analyzer has done this already.
-    }
-  }
-
-  @override
-  void visitBinaryExpression(BinaryExpression node) {
-    var op = node.operator;
-    if (op.isUserDefinableOperator) {
-      if (rules.isDynamicTarget(node.leftOperand)) {
-        // Dynamic invocation
-        // TODO(vsm): Move this logic to the resolver?
-        if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) {
-          _recordDynamicInvoke(node, node.leftOperand);
-        }
-      } else {
-        var element = node.staticElement;
-        // Method invocation.
-        if (element is MethodElement) {
-          var type = element.type;
-          // Analyzer should enforce number of parameter types, but check in
-          // case we have erroneous input.
-          if (type.normalParameterTypes.isNotEmpty) {
-            checkArgument(node.rightOperand, type.normalParameterTypes[0]);
-          }
-        } else {
-          // TODO(vsm): Assert that the analyzer found an error here?
-        }
-      }
-    } else {
-      // Non-method operator.
-      switch (op.type) {
-        case TokenType.AMPERSAND_AMPERSAND:
-        case TokenType.BAR_BAR:
-          checkBoolean(node.leftOperand);
-          checkBoolean(node.rightOperand);
-          break;
-        case TokenType.BANG_EQ:
-          break;
-        case TokenType.QUESTION_QUESTION:
-          break;
-        default:
-          assert(false);
-      }
-    }
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitConditionalExpression(ConditionalExpression node) {
-    checkBoolean(node.condition);
-    node.visitChildren(this);
-  }
-
-  @override
-  void visitIndexExpression(IndexExpression node) {
-    var target = node.realTarget;
-    if (rules.isDynamicTarget(target)) {
-      _recordDynamicInvoke(node, target);
-    } else {
-      var element = node.staticElement;
-      if (element is MethodElement) {
-        var type = element.type;
-        // Analyzer should enforce number of parameter types, but check in
-        // case we have erroneous input.
-        if (type.normalParameterTypes.isNotEmpty) {
-          checkArgument(node.index, type.normalParameterTypes[0]);
-        }
-      } else {
-        // TODO(vsm): Assert that the analyzer found an error here?
-      }
-    }
-    node.visitChildren(this);
-  }
-
-  DartType getType(TypeName name) {
-    return (name == null) ? rules.provider.dynamicType : name.type;
-  }
-
-  /// Analyzer checks boolean conversions, but we need to check too, because
-  /// it uses the default assignability rules that allow `dynamic` and `Object`
-  /// to be assigned to bool with no message.
-  void checkBoolean(Expression expr) =>
-      checkAssignment(expr, rules.provider.boolType);
-
-  void checkAssignment(Expression expr, DartType type) {
-    if (expr is ParenthesizedExpression) {
-      checkAssignment(expr.expression, type);
-    } else {
-      _recordMessage(rules.checkAssignment(expr, type));
-    }
-  }
-
-  DartType _specializedBinaryReturnType(
-      TokenType op, DartType t1, DartType t2, DartType normalReturnType) {
-    // This special cases binary return types as per 16.26 and 16.27 of the
-    // Dart language spec.
-    switch (op) {
-      case TokenType.PLUS:
-      case TokenType.MINUS:
-      case TokenType.STAR:
-      case TokenType.TILDE_SLASH:
-      case TokenType.PERCENT:
-      case TokenType.PLUS_EQ:
-      case TokenType.MINUS_EQ:
-      case TokenType.STAR_EQ:
-      case TokenType.TILDE_SLASH_EQ:
-      case TokenType.PERCENT_EQ:
-        if (t1 == rules.provider.intType &&
-            t2 == rules.provider.intType) return t1;
-        if (t1 == rules.provider.doubleType &&
-            t2 == rules.provider.doubleType) return t1;
-        // This particular combo is not spelled out in the spec, but all
-        // implementations and analyzer seem to follow this.
-        if (t1 == rules.provider.doubleType &&
-            t2 == rules.provider.intType) return t1;
-    }
-    return normalReturnType;
-  }
-
-  void _checkCompoundAssignment(AssignmentExpression expr) {
-    var op = expr.operator.type;
-    assert(op.isAssignmentOperator && op != TokenType.EQ);
-    var methodElement = expr.staticElement;
-    if (methodElement == null) {
-      // Dynamic invocation
-      _recordDynamicInvoke(expr, expr.leftHandSide);
-    } else {
-      // Sanity check the operator
-      assert(methodElement.isOperator);
-      var functionType = methodElement.type;
-      var paramTypes = functionType.normalParameterTypes;
-      assert(paramTypes.length == 1);
-      assert(functionType.namedParameterTypes.isEmpty);
-      assert(functionType.optionalParameterTypes.isEmpty);
-
-      // Check the lhs type
-      var staticInfo;
-      var rhsType = _getStaticType(expr.rightHandSide);
-      var lhsType = _getStaticType(expr.leftHandSide);
-      var returnType = _specializedBinaryReturnType(
-          op, lhsType, rhsType, functionType.returnType);
-
-      if (!rules.isSubTypeOf(returnType, lhsType)) {
-        final numType = rules.provider.numType;
-        // Try to fix up the numerical case if possible.
-        if (rules.isSubTypeOf(lhsType, numType) &&
-            rules.isSubTypeOf(lhsType, rhsType)) {
-          // This is also slightly different from spec, but allows us to keep
-          // compound operators in the int += num and num += dynamic cases.
-          staticInfo = DownCast.create(
-              rules, expr.rightHandSide, Coercion.cast(rhsType, lhsType));
-          rhsType = lhsType;
-        } else {
-          // Static type error
-          staticInfo = new StaticTypeError(rules, expr, lhsType);
-        }
-        _recordMessage(staticInfo);
-      }
-
-      // Check the rhs type
-      if (staticInfo is! CoercionInfo) {
-        var paramType = paramTypes.first;
-        staticInfo = rules.checkAssignment(expr.rightHandSide, paramType);
-        _recordMessage(staticInfo);
-      }
-    }
-  }
-
-  bool _isObjectGetter(Expression target, SimpleIdentifier id) {
-    PropertyAccessorElement element =
-        rules.provider.objectType.element.getGetter(id.name);
-    return (element != null && !element.isStatic);
-  }
-
-  bool _isObjectMethod(Expression target, SimpleIdentifier id) {
-    MethodElement element =
-        rules.provider.objectType.element.getMethod(id.name);
-    return (element != null && !element.isStatic);
-  }
-
-  bool _isObjectProperty(Expression target, SimpleIdentifier id) {
-    return _isObjectGetter(target, id) || _isObjectMethod(target, id);
-  }
-
-  DartType _getStaticType(Expression expr) {
-    var type = expr.staticType;
-    if (type == null) {
-      reporter.onError(new MissingTypeError(expr).toAnalysisError());
-    }
-    return type ?? rules.provider.dynamicType;
-  }
-
-  void _recordDynamicInvoke(AstNode node, AstNode target) {
-    reporter.onError(new DynamicInvoke(rules, node).toAnalysisError());
-    // TODO(jmesserly): we may eventually want to record if the whole operation
-    // (node) was dynamic, rather than the target, but this is an easier fit
-    // with what we used to do.
-    DynamicInvoke.set(target, true);
-  }
-
-  void _recordMessage(StaticInfo info) {
-    if (info == null) return;
-    var error = info.toAnalysisError();
-    if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true;
-    reporter.onError(error);
-
-    if (info is CoercionInfo) {
-      // TODO(jmesserly): if we're run again on the same AST, we'll produce the
-      // same annotations. This should be harmless. This might go away once
-      // CodeChecker is integrated better with analyzer, as it will know that
-      // checking has already been performed.
-      // assert(CoercionInfo.get(info.node) == null);
-      CoercionInfo.set(info.node, info);
-    }
-  }
-}
+export 'package:analyzer/src/task/strong/checker.dart';
diff --git a/lib/src/checker/resolver.dart b/lib/src/checker/resolver.dart
index f05998e..1e141cf 100644
--- a/lib/src/checker/resolver.dart
+++ b/lib/src/checker/resolver.dart
@@ -19,6 +19,7 @@
 
 import '../../strong_mode.dart' show StrongModeOptions;
 import '../utils.dart';
+import 'rules.dart';
 
 final _log = new logger.Logger('dev_compiler.src.resolver');
 
diff --git a/lib/src/checker/rules.dart b/lib/src/checker/rules.dart
index f4d35bc..eebfcac 100644
--- a/lib/src/checker/rules.dart
+++ b/lib/src/checker/rules.dart
@@ -4,731 +4,4 @@
 
 library dev_compiler.src.checker.rules;
 
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-
-import '../../strong_mode.dart' show StrongModeOptions;
-import '../info.dart';
-import '../utils.dart' as utils;
-
-class TypeRules {
-  final TypeProvider provider;
-
-  /// Map of fields / properties / methods on Object.
-  final Map<String, DartType> objectMembers;
-
-  final StrongModeOptions options;
-  DownwardsInference inferrer;
-
-  TypeRules(TypeProvider provider, {this.options})
-      : provider = provider,
-        objectMembers = utils.getObjectMemberMap(provider) {
-    inferrer = new DownwardsInference(this);
-  }
-
-  /// Given a type t, if t is an interface type with a call method
-  /// defined, return the function type for the call method, otherwise
-  /// return null.
-  FunctionType getCallMethodType(DartType t) {
-    if (t is InterfaceType) {
-      ClassElement element = t.element;
-      InheritanceManager manager = new InheritanceManager(element.library);
-      FunctionType callType = manager.lookupMemberType(t, "call");
-      return callType;
-    }
-    return null;
-  }
-
-  /// Given an expression, return its type assuming it is
-  /// in the caller position of a call (that is, accounting
-  /// for the possibility of a call method).  Returns null
-  /// if expression is not statically callable.
-  FunctionType getTypeAsCaller(Expression applicand) {
-    var t = getStaticType(applicand);
-    if (t is InterfaceType) {
-      return getCallMethodType(t);
-    }
-    if (t is FunctionType) return t;
-    return null;
-  }
-
-  /// Gets the expected return type of the given function [body], either from
-  /// a normal return/yield, or from a yield*.
-  DartType getExpectedReturnType(FunctionBody body, {bool yieldStar: false}) {
-    FunctionType functionType;
-    var parent = body.parent;
-    if (parent is Declaration) {
-      functionType = elementType(parent.element);
-    } else {
-      assert(parent is FunctionExpression);
-      functionType = getStaticType(parent);
-    }
-
-    var type = functionType.returnType;
-
-    InterfaceType expectedType = null;
-    if (body.isAsynchronous) {
-      if (body.isGenerator) {
-        // Stream<T> -> T
-        expectedType = provider.streamType;
-      } else {
-        // Future<T> -> T
-        // TODO(vsm): Revisit with issue #228.
-        expectedType = provider.futureType;
-      }
-    } else {
-      if (body.isGenerator) {
-        // Iterable<T> -> T
-        expectedType = provider.iterableType;
-      } else {
-        // T -> T
-        return type;
-      }
-    }
-    if (yieldStar) {
-      if (type.isDynamic) {
-        // Ensure it's at least a Stream / Iterable.
-        return expectedType.substitute4([provider.dynamicType]);
-      } else {
-        // Analyzer will provide a separate error if expected type
-        // is not compatible with type.
-        return type;
-      }
-    }
-    if (type.isDynamic) {
-      return type;
-    } else if (type is InterfaceType && type.element == expectedType.element) {
-      return type.typeArguments[0];
-    } else {
-      // Malformed type - fallback on analyzer error.
-      return null;
-    }
-  }
-
-  DartType getStaticType(Expression expr) {
-    return expr.staticType ?? provider.dynamicType;
-  }
-
-  bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
-    if (t.isDynamic && dynamicIsBottom) return true;
-    // TODO(vsm): We need direct support for non-nullability in DartType.
-    // This should check on "true/nonnullable" Bottom
-    if (t.isBottom) return true;
-    return false;
-  }
-
-  bool _isTop(DartType t, {bool dynamicIsBottom: false}) {
-    if (t.isDynamic && !dynamicIsBottom) return true;
-    if (t.isObject) return true;
-    return false;
-  }
-
-  bool _anyParameterType(FunctionType ft, bool predicate(DartType t)) {
-    return ft.normalParameterTypes.any(predicate) ||
-        ft.optionalParameterTypes.any(predicate) ||
-        ft.namedParameterTypes.values.any(predicate);
-  }
-
-  // TODO(leafp): Revisit this.
-  bool isGroundType(DartType t) {
-    if (t is TypeParameterType) return false;
-    if (_isTop(t)) return true;
-
-    if (t is FunctionType) {
-      if (!_isTop(t.returnType) ||
-          _anyParameterType(t, (pt) => !_isBottom(pt, dynamicIsBottom: true))) {
-        return false;
-      } else {
-        return true;
-      }
-    }
-
-    if (t is InterfaceType) {
-      var typeArguments = t.typeArguments;
-      for (var typeArgument in typeArguments) {
-        if (!_isTop(typeArgument)) return false;
-      }
-      return true;
-    }
-
-    // We should not see any other type aside from malformed code.
-    return false;
-  }
-
-  /// Check that f1 is a subtype of f2. [ignoreReturn] is used in the DDC
-  /// checker to determine whether f1 would be a subtype of f2 if the return
-  /// type of f1 is set to match f2's return type.
-  // [fuzzyArrows] indicates whether or not the f1 and f2 should be
-  // treated as fuzzy arrow types (and hence dynamic parameters to f2 treated as
-  // bottom).
-  bool isFunctionSubTypeOf(FunctionType f1, FunctionType f2,
-      {bool fuzzyArrows: true, bool ignoreReturn: false}) {
-    final r1s = f1.normalParameterTypes;
-    final o1s = f1.optionalParameterTypes;
-    final n1s = f1.namedParameterTypes;
-    final r2s = f2.normalParameterTypes;
-    final o2s = f2.optionalParameterTypes;
-    final n2s = f2.namedParameterTypes;
-    final ret1 = ignoreReturn ? f2.returnType : f1.returnType;
-    final ret2 = f2.returnType;
-
-    // A -> B <: C -> D if C <: A and
-    // either D is void or B <: D
-    if (!ret2.isVoid && !isSubTypeOf(ret1, ret2)) return false;
-
-    // Reject if one has named and the other has optional
-    if (n1s.length > 0 && o2s.length > 0) return false;
-    if (n2s.length > 0 && o1s.length > 0) return false;
-
-    // f2 has named parameters
-    if (n2s.length > 0) {
-      // Check that every named parameter in f2 has a match in f1
-      for (String k2 in n2s.keys) {
-        if (!n1s.containsKey(k2)) return false;
-        if (!isSubTypeOf(n2s[k2], n1s[k2],
-            dynamicIsBottom: fuzzyArrows)) return false;
-      }
-    }
-    // If we get here, we either have no named parameters,
-    // or else the named parameters match and we have no optional
-    // parameters
-
-    // If f1 has more required parameters, reject
-    if (r1s.length > r2s.length) return false;
-
-    // If f2 has more required + optional parameters, reject
-    if (r2s.length + o2s.length > r1s.length + o1s.length) return false;
-
-    // The parameter lists must look like the following at this point
-    // where rrr is a region of required, and ooo is a region of optionals.
-    // f1: rrr ooo ooo ooo
-    // f2: rrr rrr ooo
-    int rr = r1s.length; // required in both
-    int or = r2s.length - r1s.length; // optional in f1, required in f2
-    int oo = o2s.length; // optional in both
-
-    for (int i = 0; i < rr; ++i) {
-      if (!isSubTypeOf(r2s[i], r1s[i],
-          dynamicIsBottom: fuzzyArrows)) return false;
-    }
-    for (int i = 0, j = rr; i < or; ++i, ++j) {
-      if (!isSubTypeOf(r2s[j], o1s[i],
-          dynamicIsBottom: fuzzyArrows)) return false;
-    }
-    for (int i = or, j = 0; i < oo; ++i, ++j) {
-      if (!isSubTypeOf(o2s[j], o1s[i],
-          dynamicIsBottom: fuzzyArrows)) return false;
-    }
-    return true;
-  }
-
-  bool _isInterfaceSubTypeOf(InterfaceType i1, InterfaceType i2) {
-    if (i1 == i2) return true;
-
-    if (i1.element == i2.element) {
-      List<DartType> tArgs1 = i1.typeArguments;
-      List<DartType> tArgs2 = i2.typeArguments;
-
-      // TODO(leafp): Verify that this is always true
-      // Do raw types get filled in?
-      assert(tArgs1.length == tArgs2.length);
-
-      for (int i = 0; i < tArgs1.length; i++) {
-        DartType t1 = tArgs1[i];
-        DartType t2 = tArgs2[i];
-        if (!isSubTypeOf(t1, t2)) return false;
-      }
-      return true;
-    }
-
-    if (i2.isDartCoreFunction) {
-      if (i1.element.getMethod("call") != null) return true;
-    }
-
-    if (i1 == provider.objectType) return false;
-
-    if (_isInterfaceSubTypeOf(i1.superclass, i2)) return true;
-
-    for (final parent in i1.interfaces) {
-      if (_isInterfaceSubTypeOf(parent, i2)) return true;
-    }
-
-    for (final parent in i1.mixins) {
-      if (_isInterfaceSubTypeOf(parent, i2)) return true;
-    }
-
-    return false;
-  }
-
-  bool isSubTypeOf(DartType t1, DartType t2, {bool dynamicIsBottom: false}) {
-    if (t1 == t2) return true;
-
-    // Trivially true.
-    if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
-        _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
-      return true;
-    }
-
-    // Trivially false.
-    if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
-        _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
-      return false;
-    }
-
-    // The null type is a subtype of any nullable type, which is all Dart types.
-    // TODO(vsm): Note, t1.isBottom still allows for null confusingly.
-    // _isBottom(t1) does not necessarily imply t1.isBottom if there are
-    // nonnullable types in the system.
-    if (t1.isBottom) {
-      return true;
-    }
-
-    // S <: T where S is a type variable
-    //  T is not dynamic or object (handled above)
-    //  S != T (handled above)
-    //  So only true if bound of S is S' and
-    //  S' <: T
-    if (t1 is TypeParameterType) {
-      DartType bound = t1.element.bound;
-      if (bound == null) return false;
-      return isSubTypeOf(bound, t2);
-    }
-
-    if (t2 is TypeParameterType) {
-      return false;
-    }
-
-    if (t2.isDartCoreFunction) {
-      if (t1 is FunctionType) return true;
-      if (t1.element is ClassElement) {
-        if ((t1.element as ClassElement).getMethod("call") != null) return true;
-      }
-    }
-
-    // "Traditional" name-based subtype check.
-    if (t1 is InterfaceType && t2 is InterfaceType) {
-      return _isInterfaceSubTypeOf(t1, t2);
-    }
-
-    if (t1 is! FunctionType && t2 is! FunctionType) return false;
-
-    if (t1 is InterfaceType && t2 is FunctionType) {
-      var callType = getCallMethodType(t1);
-      if (callType == null) return false;
-      return isFunctionSubTypeOf(callType, t2);
-    }
-
-    if (t1 is FunctionType && t2 is InterfaceType) {
-      return false;
-    }
-
-    // Functions
-    // Note: it appears under the hood all Dart functions map to a class /
-    // hidden type that:
-    //  (a) subtypes Object (an internal _FunctionImpl in the VM)
-    //  (b) implements Function
-    //  (c) provides standard Object members (hashCode, toString)
-    //  (d) contains private members (corresponding to _FunctionImpl?)
-    //  (e) provides a call method to handle the actual function invocation
-    //
-    // The standard Dart subtyping rules are structural in nature.  I.e.,
-    // bivariant on arguments and return type.
-    //
-    // The below tries for a more traditional subtyping rule:
-    // - covariant on return type
-    // - contravariant on parameters
-    // - 'sensible' (?) rules on optional and/or named params
-    // but doesn't properly mix with class subtyping.  I suspect Java 8 lambdas
-    // essentially map to dynamic (and rely on invokedynamic) due to similar
-    // issues.
-    return isFunctionSubTypeOf(t1 as FunctionType, t2 as FunctionType);
-  }
-
-  bool isAssignable(DartType t1, DartType t2) {
-    return isSubTypeOf(t1, t2);
-  }
-
-  // Produce a coercion which coerces something of type fromT
-  // to something of type toT.
-  // If wrap is true and both are function types, a closure
-  // wrapper coercion is produced using _wrapTo (see above)
-  // Returns the error coercion if the types cannot be coerced
-  // according to our current criteria.
-  Coercion _coerceTo(DartType fromT, DartType toT) {
-    // We can use anything as void
-    if (toT.isVoid) return Coercion.identity(toT);
-
-    // fromT <: toT, no coercion needed
-    if (isSubTypeOf(fromT, toT)) return Coercion.identity(toT);
-
-    // For now, reject conversions between function types and
-    // call method objects.  We could choose to allow casts here.
-    // Wrapping a function type to assign it to a call method
-    // object will never succeed.  Wrapping the other way could
-    // be allowed.
-    if ((fromT is FunctionType && getCallMethodType(toT) != null) ||
-        (toT is FunctionType && getCallMethodType(fromT) != null)) {
-      return Coercion.error();
-    }
-
-    // Downcast if toT <: fromT
-    if (isSubTypeOf(toT, fromT)) return Coercion.cast(fromT, toT);
-
-    // Downcast if toT <===> fromT
-    // The intention here is to allow casts that are sideways in the restricted
-    // type system, but allowed in the regular dart type system, since these
-    // are likely to succeed.  The canonical example is List<dynamic> and
-    // Iterable<T> for some concrete T (e.g. Object).  These are unrelated
-    // in the restricted system, but List<dynamic> <: Iterable<T> in dart.
-    if (fromT.isAssignableTo(toT)) {
-      return Coercion.cast(fromT, toT);
-    }
-    return Coercion.error();
-  }
-
-  StaticInfo checkAssignment(Expression expr, DartType toT) {
-    final fromT = getStaticType(expr);
-    final Coercion c = _coerceTo(fromT, toT);
-    if (c is Identity) return null;
-    if (c is CoercionError) return new StaticTypeError(this, expr, toT);
-    var reason = null;
-
-    var errors = <String>[];
-    var ok = inferrer.inferExpression(expr, toT, errors);
-    if (ok) return InferredType.create(this, expr, toT);
-    reason = (errors.isNotEmpty) ? errors.first : null;
-
-    if (c is Cast) return DownCast.create(this, expr, c, reason: reason);
-    assert(false);
-    return null;
-  }
-
-  DartType elementType(Element e) {
-    if (e == null) {
-      // Malformed code - just return dynamic.
-      return provider.dynamicType;
-    }
-    return (e as dynamic).type;
-  }
-
-  /// Returns `true` if the target expression is dynamic.
-  // TODO(jmesserly): remove this in favor of utils? Or a static method here?
-  bool isDynamicTarget(Expression target) => utils.isDynamicTarget(target);
-
-  /// Returns `true` if the expression is a dynamic function call or method
-  /// invocation.
-  bool isDynamicCall(Expression call) {
-    var ft = getTypeAsCaller(call);
-    // TODO(leafp): This will currently return true if t is Function
-    // This is probably the most correct thing to do for now, since
-    // this code is also used by the back end.  Maybe revisit at some
-    // point?
-    if (ft == null) return true;
-    // Dynamic as the parameter type is treated as bottom.  A function with
-    // a dynamic parameter type requires a dynamic call in general.
-    // However, as an optimization, if we have an original definition, we know
-    // dynamic is reified as Object - in this case a regular call is fine.
-    if (call is SimpleIdentifier) {
-      var element = call.staticElement;
-      if (element is FunctionElement || element is MethodElement) {
-        // An original declaration.
-        return false;
-      }
-    }
-
-    return _anyParameterType(ft, (pt) => pt.isDynamic);
-  }
-}
-
-class DownwardsInference {
-  final TypeRules rules;
-
-  DownwardsInference(this.rules);
-
-  /// Called for each list literal which gets inferred
-  void annotateListLiteral(ListLiteral e, List<DartType> targs) {}
-
-  /// Called for each map literal which gets inferred
-  void annotateMapLiteral(MapLiteral e, List<DartType> targs) {}
-
-  /// Called for each new/const which gets inferred
-  void annotateInstanceCreationExpression(
-      InstanceCreationExpression e, List<DartType> targs) {}
-
-  /// Called for cast from dynamic required for inference to succeed
-  void annotateCastFromDynamic(Expression e, DartType t) {}
-
-  /// Called for each function expression return type inferred
-  void annotateFunctionExpression(FunctionExpression e, DartType returnType) {}
-
-  /// Downward inference
-  bool inferExpression(Expression e, DartType t, List<String> errors) {
-    // Don't cast top level expressions, only sub-expressions
-    return _inferExpression(e, t, errors, cast: false);
-  }
-
-  /// Downward inference
-  bool _inferExpression(Expression e, DartType t, List<String> errors,
-      {cast: true}) {
-    if (e is ConditionalExpression) {
-      return _inferConditionalExpression(e, t, errors);
-    }
-    if (e is ParenthesizedExpression) {
-      return _inferParenthesizedExpression(e, t, errors);
-    }
-    if (rules.isSubTypeOf(rules.getStaticType(e), t)) return true;
-    if (cast && rules.getStaticType(e).isDynamic) {
-      annotateCastFromDynamic(e, t);
-      return true;
-    }
-    if (e is FunctionExpression) return _inferFunctionExpression(e, t, errors);
-    if (e is ListLiteral) return _inferListLiteral(e, t, errors);
-    if (e is MapLiteral) return _inferMapLiteral(e, t, errors);
-    if (e is NamedExpression) return _inferNamedExpression(e, t, errors);
-    if (e is InstanceCreationExpression) {
-      return _inferInstanceCreationExpression(e, t, errors);
-    }
-    errors.add("$e cannot be typed as $t");
-    return false;
-  }
-
-  /// If t1 = I<dynamic, ..., dynamic>, then look for a supertype
-  /// of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'>
-  /// If the supertype exists, use the constraints S0 <: S0', ... Sm <: Sm'
-  /// to derive a concrete instantation for I of the form <T0, ..., Tn>,
-  /// such that I<T0, .., Tn> <: t2
-  List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) {
-    if (t1 == t2) return t2.typeArguments;
-    var tArgs1 = t1.typeArguments;
-    var tArgs2 = t2.typeArguments;
-    // If t1 isn't a raw type, bail out
-    if (tArgs1 != null && tArgs1.any((t) => !t.isDynamic)) return null;
-
-    // This is our inferred type argument list.  We start at all dynamic,
-    // and fill in with inferred types when we reach a match.
-    var actuals =
-        new List<DartType>.filled(tArgs1.length, rules.provider.dynamicType);
-
-    // When we find the supertype of t1 with the same
-    // classname as t2 (see below), we have the following:
-    // If t1 is an instantiation of a class T1<X0, ..., Xn>
-    // and t2 is an instantiation of a class T2<Y0, ...., Ym>
-    // of the form t2 = T2<S0, ..., Sm>
-    // then we want to choose instantiations for the Xi
-    // T0, ..., Tn such that T1<T0, ..., Tn> <: t2 .
-    // To find this, we simply instantate T1 with
-    // X0, ..., Xn, and then find its superclass
-    // T2<T0', ..., Tn'>.  We then solve the constraint
-    // set T0' <: S0, ..., Tn' <: Sn for the Xi.
-    // Currently, we only handle constraints where
-    // the Ti' is one of the Xi'.  If there are multiple
-    // constraints on some Xi, we choose the lower of the
-    // two (if it exists).
-    bool permute(List<DartType> permutedArgs) {
-      if (permutedArgs == null) return false;
-      var ps = t1.typeParameters;
-      var ts = ps.map((p) => p.type).toList();
-      for (int i = 0; i < permutedArgs.length; i++) {
-        var tVar = permutedArgs[i];
-        var tActual = tArgs2[i];
-        var index = ts.indexOf(tVar);
-        if (index >= 0 && rules.isSubTypeOf(tActual, actuals[index])) {
-          actuals[index] = tActual;
-        }
-      }
-      return actuals.any((x) => !x.isDynamic);
-    }
-
-    // Look for the first supertype of t1 with the same class name as t2.
-    bool match(InterfaceType t1) {
-      if (t1.element == t2.element) {
-        return permute(t1.typeArguments);
-      }
-
-      if (t1 == rules.provider.objectType) return false;
-
-      if (match(t1.superclass)) return true;
-
-      for (final parent in t1.interfaces) {
-        if (match(parent)) return true;
-      }
-
-      for (final parent in t1.mixins) {
-        if (match(parent)) return true;
-      }
-      return false;
-    }
-
-    // We have that t1 = T1<dynamic, ..., dynamic>.
-    // To match t1 against t2, we use the uninstantiated version
-    // of t1, essentially treating it as an instantiation with
-    // fresh variables, and solve for the variables.
-    // t1.element.type will be of the form T1<X0, ..., Xn>
-    if (!match(t1.element.type)) return null;
-    var newT1 = t1.element.type.substitute4(actuals);
-    // If we found a solution, return it.
-    if (rules.isSubTypeOf(newT1, t2)) return actuals;
-    return null;
-  }
-
-  /// These assume that e is not already a subtype of t
-
-  bool _inferConditionalExpression(
-      ConditionalExpression e, DartType t, errors) {
-    return _inferExpression(e.thenExpression, t, errors) &&
-        _inferExpression(e.elseExpression, t, errors);
-  }
-
-  bool _inferParenthesizedExpression(
-      ParenthesizedExpression e, DartType t, errors) {
-    return _inferExpression(e.expression, t, errors);
-  }
-
-  bool _inferInstanceCreationExpression(
-      InstanceCreationExpression e, DartType t, errors) {
-    var arguments = e.argumentList.arguments;
-    var rawType = rules.getStaticType(e);
-    // rawType is the instantiated type of the instance
-    if (rawType is! InterfaceType) return false;
-    var type = (rawType as InterfaceType);
-    if (type.typeParameters == null ||
-        type.typeParameters.length == 0) return false;
-    if (e.constructorName.type == null) return false;
-    // classTypeName is the type name of the class being instantiated
-    var classTypeName = e.constructorName.type;
-    // Check that we were not passed any type arguments
-    if (classTypeName.typeArguments != null) return false;
-    // Infer type arguments
-    if (t is! InterfaceType) return false;
-    var targs = _matchTypes(type, t);
-    if (targs == null) return false;
-    if (e.staticElement == null) return false;
-    var constructorElement = e.staticElement;
-    // From the constructor element get:
-    //  the instantiated type of the constructor, then
-    //     the uninstantiated element for the constructor, then
-    //        the uninstantiated type for the constructor
-    var rawConstructorElement =
-        constructorElement.type.element as ConstructorElement;
-    var baseType = rawConstructorElement.type;
-    if (baseType == null) return false;
-    // From the interface type (instantiated), get:
-    //  the uninstantiated element, then
-    //    the uninstantiated type, then
-    //      the type arguments (aka the type parameters)
-    var tparams = type.element.type.typeArguments;
-    // Take the uninstantiated constructor type, and replace the type
-    // parameters with the inferred arguments.
-    var fType = baseType.substitute2(targs, tparams);
-    {
-      var rTypes = fType.normalParameterTypes;
-      var oTypes = fType.optionalParameterTypes;
-      var pTypes = new List.from(rTypes)..addAll(oTypes);
-      var pArgs = arguments.where((x) => x is! NamedExpression);
-      var pi = 0;
-      for (var arg in pArgs) {
-        if (pi >= pTypes.length) return false;
-        var argType = pTypes[pi];
-        if (!_inferExpression(arg, argType, errors)) return false;
-        pi++;
-      }
-      var nTypes = fType.namedParameterTypes;
-      for (var arg0 in arguments) {
-        if (arg0 is! NamedExpression) continue;
-        var arg = arg0 as NamedExpression;
-        SimpleIdentifier nameNode = arg.name.label;
-        String name = nameNode.name;
-        var argType = nTypes[name];
-        if (argType == null) return false;
-        if (!_inferExpression(arg, argType, errors)) return false;
-      }
-    }
-    annotateInstanceCreationExpression(e, targs);
-    return true;
-  }
-
-  bool _inferNamedExpression(NamedExpression e, DartType t, errors) {
-    return _inferExpression(e.expression, t, errors);
-  }
-
-  bool _inferFunctionExpression(FunctionExpression e, DartType t, errors) {
-    if (t is! FunctionType) return false;
-    var fType = t as FunctionType;
-    var eType = e.staticType as FunctionType;
-    if (eType is! FunctionType) return false;
-
-    // We have a function literal, so we can treat the arrow type
-    // as non-fuzzy.  Since we're not improving on parameter types
-    // currently, if this check fails then we cannot succeed, so
-    // bail out.  Otherwise, we never need to check the parameter types
-    // again.
-    if (!rules.isFunctionSubTypeOf(eType, fType,
-        fuzzyArrows: false, ignoreReturn: true)) return false;
-
-    // This only entered inference because of fuzzy typing.
-    // The function type is already specific enough, we can just
-    // succeed and treat it as a successful inference
-    if (rules.isSubTypeOf(eType.returnType, fType.returnType)) return true;
-
-    // Fuzzy typing again, handle the void case (not caught by the previous)
-    if (fType.returnType.isVoid) return true;
-
-    if (e.body is! ExpressionFunctionBody) return false;
-    var body = (e.body as ExpressionFunctionBody).expression;
-    if (!_inferExpression(body, fType.returnType, errors)) return false;
-
-    // TODO(leafp): Try narrowing the argument types if possible
-    // to get better code in the function body.  This requires checking
-    // that the body is well-typed at the more specific type.
-
-    // At this point, we know that the parameter types are in the appropriate subtype
-    // relation, and we have checked that we can type the body at the appropriate return
-    // type, so we can are done.
-    annotateFunctionExpression(e, fType.returnType);
-    return true;
-  }
-
-  bool _inferListLiteral(ListLiteral e, DartType t, errors) {
-    var dyn = rules.provider.dynamicType;
-    var listT = rules.provider.listType.substitute4([dyn]);
-    // List <: t (using dart rules) must be true
-    if (!listT.isSubtypeOf(t)) return false;
-    // The list literal must have no type arguments
-    if (e.typeArguments != null) return false;
-    if (t is! InterfaceType) return false;
-    var targs = _matchTypes(listT, t);
-    if (targs == null) return false;
-    assert(targs.length == 1);
-    var etype = targs[0];
-    assert(!etype.isDynamic);
-    var elements = e.elements;
-    var b = elements.every((e) => _inferExpression(e, etype, errors));
-    if (b) annotateListLiteral(e, targs);
-    return b;
-  }
-
-  bool _inferMapLiteral(MapLiteral e, DartType t, errors) {
-    var dyn = rules.provider.dynamicType;
-    var mapT = rules.provider.mapType.substitute4([dyn, dyn]);
-    // Map <: t (using dart rules) must be true
-    if (!mapT.isSubtypeOf(t)) return false;
-    // The map literal must have no type arguments
-    if (e.typeArguments != null) return false;
-    if (t is! InterfaceType) return false;
-    var targs = _matchTypes(mapT, t);
-    if (targs == null) return false;
-    assert(targs.length == 2);
-    var kType = targs[0];
-    var vType = targs[1];
-    assert(!(kType.isDynamic && vType.isDynamic));
-    var entries = e.entries;
-    bool inferEntry(MapLiteralEntry entry) {
-      return _inferExpression(entry.key, kType, errors) &&
-          _inferExpression(entry.value, vType, errors);
-    }
-    var b = entries.every(inferEntry);
-    if (b) annotateMapLiteral(e, targs);
-    return b;
-  }
-}
+export 'package:analyzer/src/task/strong/rules.dart';
diff --git a/lib/src/codegen/code_generator.dart b/lib/src/codegen/code_generator.dart
index eb4135d..12cc751 100644
--- a/lib/src/codegen/code_generator.dart
+++ b/lib/src/codegen/code_generator.dart
@@ -23,7 +23,7 @@
 
   CodeGenerator(AbstractCompiler compiler)
       : compiler = compiler,
-        rules = compiler.rules,
+        rules = new TypeRules(compiler.context.typeProvider),
         context = compiler.context,
         options = compiler.options.codegenOptions;
 
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index 99a2408..872a7a5 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -105,11 +105,10 @@
 
   Map<String, DartType> _objectMembers;
 
-  JSCodegenVisitor(AbstractCompiler compiler, this.currentLibrary,
+  JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary,
       this._extensionTypes, this._fieldsNeedingStorage)
       : compiler = compiler,
         options = compiler.options.codegenOptions,
-        rules = compiler.rules,
         _types = compiler.context.typeProvider {
     _loader = new ModuleItemLoadOrder(_emitModuleItem);
 
@@ -125,7 +124,7 @@
 
   JS.Program emitLibrary(LibraryUnit library) {
     // Modify the AST to make coercions explicit.
-    new CoercionReifier(library, compiler).reify();
+    new CoercionReifier(library, rules).reify();
 
     // Build the public namespace for this library. This allows us to do
     // constant time lookups (contrast with `Element.getChild(name)`).
@@ -3280,7 +3279,7 @@
     var library = unit.library.element.library;
     var fields = findFieldsNeedingStorage(unit);
     var codegen =
-        new JSCodegenVisitor(compiler, library, _extensionTypes, fields);
+        new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields);
     var module = codegen.emitLibrary(unit);
     var out = compiler.getOutputPath(library.source.uri);
     return writeJsLibrary(module, out,
diff --git a/lib/src/codegen/reify_coercions.dart b/lib/src/codegen/reify_coercions.dart
index 8a2c542..3bf1d91 100644
--- a/lib/src/codegen/reify_coercions.dart
+++ b/lib/src/codegen/reify_coercions.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/generated/element.dart';
 import 'package:logging/logging.dart' as logger;
 
-import '../compiler.dart' show AbstractCompiler;
 import '../checker/rules.dart';
 import '../info.dart';
 
@@ -100,11 +99,11 @@
   CoercionReifier._(
       this._cm, this._tm, this._vm, this._library, this._inferrer);
 
-  factory CoercionReifier(LibraryUnit library, AbstractCompiler compiler) {
+  factory CoercionReifier(LibraryUnit library, TypeRules rules) {
     var vm = new VariableManager();
     var tm = new TypeManager(library.library.element.enclosingElement, vm);
     var cm = new CoercionManager(vm, tm);
-    var inferrer = new _Inference(compiler.rules, tm);
+    var inferrer = new _Inference(rules, tm);
     return new CoercionReifier._(cm, tm, vm, library, inferrer);
   }
 
diff --git a/lib/src/compiler.dart b/lib/src/compiler.dart
index 8194518..d4f61a4 100644
--- a/lib/src/compiler.dart
+++ b/lib/src/compiler.dart
@@ -25,8 +25,6 @@
 import 'package:path/path.dart' as path;
 
 import 'analysis_context.dart';
-import 'checker/checker.dart';
-import 'checker/rules.dart';
 import 'codegen/html_codegen.dart' as html_codegen;
 import 'codegen/js_codegen.dart';
 import 'info.dart'
@@ -100,7 +98,7 @@
     _dartCore = context.typeProvider.objectType.element.library;
   }
 
-  ErrorCollector get reporter => checker.reporter;
+  ErrorCollector get reporter => super.reporter;
 
   /// Compiles every file in [options.inputs].
   /// Returns true on successful compile.
@@ -211,10 +209,7 @@
     for (var element in unitElements) {
       var unit = context.resolveCompilationUnit(element.source, library);
       units.add(unit);
-      failureInLib = logErrors(element.source) || failureInLib;
-      checker.reset();
-      checker.visitCompilationUnit(unit);
-      if (checker.failure) failureInLib = true;
+      failureInLib = computeErrors(element.source) || failureInLib;
     }
     if (failureInLib) _compilationRecord[library] = false;
 
@@ -345,19 +340,11 @@
 abstract class AbstractCompiler {
   final CompilerOptions options;
   final AnalysisContext context;
-  final CodeChecker checker;
+  final AnalysisErrorListener reporter;
 
-  AbstractCompiler(AnalysisContext context, CompilerOptions options,
-      [AnalysisErrorListener reporter])
-      : context = context,
-        options = options,
-        checker = new CodeChecker(
-            new TypeRules(context.typeProvider, options: options.strongOptions),
-            reporter ?? AnalysisErrorListener.NULL_LISTENER);
+  AbstractCompiler(this.context, this.options, [this.reporter]);
 
   String get outputDir => options.codegenOptions.outputDir;
-  TypeRules get rules => checker.rules;
-  AnalysisErrorListener get reporter => checker.reporter;
 
   Uri stringToUri(String uriString) {
     var uri = uriString.startsWith('dart:') || uriString.startsWith('package:')
@@ -440,23 +427,33 @@
 
   /// Log any errors encountered when resolving [source] and return whether any
   /// errors were found.
-  bool logErrors(Source source) {
-    List<AnalysisError> errors = context.computeErrors(source);
+  bool computeErrors(Source source) {
+    AnalysisContext errorContext = context;
+    // TODO(jmesserly): should this be a fix somewhere in analyzer?
+    // otherwise we fail to find the parts.
+    if (source.uri.scheme == 'dart') {
+      errorContext = context.sourceFactory.dartSdk.context;
+    }
+    List<AnalysisError> errors = errorContext.computeErrors(source);
     bool failure = false;
-    if (errors.isNotEmpty) {
-      for (var error in errors) {
-        // Always skip TODOs.
-        if (error.errorCode.type == ErrorType.TODO) continue;
+    for (var error in errors) {
+      // Always skip TODOs.
+      if (error.errorCode.type == ErrorType.TODO) continue;
 
-        // Skip hints for now. In the future these could be turned on via flags.
-        if (error.errorCode.errorSeverity.ordinal <
-            ErrorSeverity.WARNING.ordinal) {
-          continue;
+      // TODO(jmesserly): for now, treat DDC errors as having a different
+      // error level from Analayzer ones.
+      if (error.errorCode.name.startsWith('dev_compiler')) {
+        reporter.onError(error);
+        if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) {
+          failure = true;
         }
-
+      } else if (error.errorCode.errorSeverity.ordinal >=
+          ErrorSeverity.WARNING.ordinal) {
         // All analyzer warnings or errors are errors for DDC.
         failure = true;
         reporter.onError(error);
+      } else {
+        // Skip hints for now.
       }
     }
     return failure;
diff --git a/lib/src/info.dart b/lib/src/info.dart
index c48fb36..75e74a3 100644
--- a/lib/src/info.dart
+++ b/lib/src/info.dart
@@ -8,20 +8,19 @@
 
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
 
-import 'checker/rules.dart';
 import 'utils.dart' as utils;
+import 'package:analyzer/src/task/strong/info.dart';
+export 'package:analyzer/src/task/strong/info.dart';
 
 /// Represents a summary of the results collected by running the program
 /// checker.
 class CheckerResults {
   final List<LibraryInfo> libraries;
-  final TypeRules rules;
   final bool failure;
 
-  CheckerResults(this.libraries, this.rules, this.failure);
+  CheckerResults(this.libraries, this.failure);
 }
 
 /// Computed information about each library.
@@ -102,474 +101,3 @@
     return clone;
   }
 }
-
-// The abstract type of coercions mapping one type to another.
-// This class also exposes static builder functions which
-// check for errors and reduce redundant coercions to the identity.
-abstract class Coercion {
-  final DartType fromType;
-  final DartType toType;
-  Coercion(this.fromType, this.toType);
-  static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT);
-  static Coercion identity(DartType type) => new Identity(type);
-  static Coercion error() => new CoercionError();
-}
-
-// Coercion which casts one type to another
-class Cast extends Coercion {
-  Cast(DartType fromType, DartType toType) : super(fromType, toType);
-}
-
-// The identity coercion
-class Identity extends Coercion {
-  Identity(DartType fromType) : super(fromType, fromType);
-}
-
-// The error coercion.  This coercion signals that a coercion
-// could not be generated.  The code generator should not see
-// these.
-class CoercionError extends Coercion {
-  CoercionError() : super(null, null);
-}
-
-// TODO(jmesserly): this could use some refactoring. These are essentially
-// like ErrorCodes in analyzer, but we're including some details in our message.
-// Analyzer instead has template strings, and replaces '{0}' with the first
-// argument.
-abstract class StaticInfo {
-  /// AST Node this info is attached to.
-  AstNode get node;
-
-  // TODO(jmesserly): review the usage of error codes. We probably want our own,
-  // as well as some DDC specific [ErrorType]s.
-  ErrorCode toErrorCode();
-
-  // TODO(jmesserly): what convention to use here?
-  String get name => 'dev_compiler.$runtimeType';
-
-  List<Object> get arguments => [node];
-
-  AnalysisError toAnalysisError() {
-    int begin = node is AnnotatedNode
-        ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset
-        : node.offset;
-    int length = node.end - begin;
-    var source = (node.root as CompilationUnit).element.source;
-    return new AnalysisError(source, begin, length, toErrorCode(), arguments);
-  }
-}
-
-/// Implicitly injected expression conversion.
-abstract class CoercionInfo extends StaticInfo {
-  final TypeRules rules;
-
-  final Expression node;
-
-  DartType get convertedType;
-
-  CoercionInfo(this.rules, this.node);
-
-  DartType get baseType => rules.getStaticType(node);
-  DartType get staticType => convertedType;
-
-  String get message;
-  toErrorCode() => new HintCode(name, message);
-
-  static const String _propertyName = 'dev_compiler.src.info.CoercionInfo';
-
-  /// Gets the coercion info associated with this node.
-  static CoercionInfo get(AstNode node) => node.getProperty(_propertyName);
-
-  /// Sets the coercion info associated with this node.
-  static CoercionInfo set(AstNode node, CoercionInfo info) {
-    node.setProperty(_propertyName, info);
-    return info;
-  }
-}
-
-// Base class for all casts from base type to sub type.
-abstract class DownCast extends CoercionInfo {
-  Cast _cast;
-
-  DownCast._internal(TypeRules rules, Expression expression, this._cast)
-      : super(rules, expression) {
-    assert(_cast.toType != baseType &&
-        _cast.fromType == baseType &&
-        (baseType.isDynamic ||
-            // Call methods make the following non-redundant
-            _cast.toType.isSubtypeOf(baseType) ||
-            baseType.isAssignableTo(_cast.toType)));
-  }
-
-  Cast get cast => _cast;
-
-  DartType get convertedType => _cast.toType;
-
-  @override List<Object> get arguments => [node, baseType, convertedType];
-  @override String get message => '{0} ({1}) will need runtime check '
-      'to cast to type {2}';
-
-  // Factory to create correct DownCast variant.
-  static StaticInfo create(TypeRules rules, Expression expression, Cast cast,
-      {String reason}) {
-    final fromT = cast.fromType;
-    final toT = cast.toType;
-
-    // toT <:_R fromT => to <: fromT
-    // NB: classes with call methods are subtypes of function
-    // types, but the function type is not assignable to the class
-    assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT));
-
-    // Handle null call specially.
-    if (expression is NullLiteral) {
-      // TODO(vsm): Create a NullCast for this once we revisit nonnullability.
-      return new DownCastImplicit(rules, expression, cast);
-    }
-
-    // Inference "casts":
-    if (expression is Literal) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      return new StaticTypeError(rules, expression, toT, reason: reason);
-    }
-    if (expression is FunctionExpression) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      return new UninferredClosure(rules, expression, cast);
-    }
-    if (expression is InstanceCreationExpression) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      return new StaticTypeError(rules, expression, toT, reason: reason);
-    }
-
-    // Composite cast: these are more likely to fail.
-    if (!rules.isGroundType(toT)) {
-      // This cast is (probably) due to our different treatment of dynamic.
-      // It may be more likely to fail at runtime.
-      return new DownCastComposite(rules, expression, cast);
-    }
-
-    // Dynamic cast
-    if (fromT.isDynamic) {
-      return new DynamicCast(rules, expression, cast);
-    }
-
-    // Assignment cast
-    var parent = expression.parent;
-    if (parent is VariableDeclaration && (parent.initializer == expression)) {
-      return new AssignmentCast(rules, expression, cast);
-    }
-
-    // Other casts
-    return new DownCastImplicit(rules, expression, cast);
-  }
-}
-
-//
-// Standard down casts.  These casts are implicitly injected by the compiler.
-//
-
-// A down cast from dynamic to T.
-class DynamicCast extends DownCast {
-  DynamicCast(TypeRules rules, Expression expression, Cast cast)
-      : super._internal(rules, expression, cast);
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-// A down cast due to a variable declaration to a ground type.  E.g.,
-//   T x = expr;
-// where T is ground.  We exclude non-ground types as these behave differently
-// compared to standard Dart.
-class AssignmentCast extends DownCast {
-  AssignmentCast(TypeRules rules, Expression expression, Cast cast)
-      : super._internal(rules, expression, cast);
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-//
-// Temporary "casts" of allocation sites - literals, constructor invocations,
-// and closures.  These should be handled by contextual inference.  In most
-// cases, inference will be sufficient, though in some it may unmask an actual
-// error: e.g.,
-//   List<int> l = [1, 2, 3]; // Inference succeeds
-//   List<String> l = [1, 2, 3]; // Inference reveals static type error
-// We're marking all as warnings for now.
-//
-// TODO(vsm,leafp): Remove this.
-class UninferredClosure extends DownCast {
-  UninferredClosure(TypeRules rules, FunctionExpression expression, Cast cast)
-      : super._internal(rules, expression, cast);
-
-  toErrorCode() => new StaticTypeWarningCode(name, message);
-}
-
-//
-// Implicit down casts.  These are only injected by the compiler by flag.
-//
-
-// A down cast to a non-ground type.  These behave differently from standard
-// Dart and may be more likely to fail at runtime.
-class DownCastComposite extends DownCast {
-  DownCastComposite(TypeRules rules, Expression expression, Cast cast)
-      : super._internal(rules, expression, cast);
-
-  toErrorCode() => new StaticTypeWarningCode(name, message);
-}
-
-// A down cast to a non-ground type.  These behave differently from standard
-// Dart and may be more likely to fail at runtime.
-class DownCastImplicit extends DownCast {
-  DownCastImplicit(TypeRules rules, Expression expression, Cast cast)
-      : super._internal(rules, expression, cast);
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-// An inferred type for the wrapped expression, which may need to be
-// reified into the term
-abstract class InferredTypeBase extends CoercionInfo {
-  final DartType _type;
-
-  InferredTypeBase._internal(TypeRules rules, Expression expression, this._type)
-      : super(rules, expression);
-
-  DartType get type => _type;
-  DartType get convertedType => type;
-  @override String get message => '{0} has inferred type {1}';
-  @override List get arguments => [node, type];
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-// Standard / unspecialized inferred type
-class InferredType extends InferredTypeBase {
-  InferredType(TypeRules rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-
-  // Factory to create correct InferredType variant.
-  static InferredTypeBase create(
-      TypeRules rules, Expression expression, DartType type) {
-    // Specialized inference:
-    if (expression is Literal) {
-      return new InferredTypeLiteral(rules, expression, type);
-    }
-    if (expression is InstanceCreationExpression) {
-      return new InferredTypeAllocation(rules, expression, type);
-    }
-    if (expression is FunctionExpression) {
-      return new InferredTypeClosure(rules, expression, type);
-    }
-    return new InferredType(rules, expression, type);
-  }
-}
-
-// An infered type for a literal expression.
-class InferredTypeLiteral extends InferredTypeBase {
-  InferredTypeLiteral(TypeRules rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-}
-
-// An inferred type for a non-literal allocation site.
-class InferredTypeAllocation extends InferredTypeBase {
-  InferredTypeAllocation(TypeRules rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-}
-
-// An inferred type for a closure expression
-class InferredTypeClosure extends InferredTypeBase {
-  InferredTypeClosure(TypeRules rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-}
-
-class DynamicInvoke extends CoercionInfo {
-  DynamicInvoke(TypeRules rules, Expression expression)
-      : super(rules, expression);
-
-  DartType get convertedType => rules.provider.dynamicType;
-  String get message => '{0} requires dynamic invoke';
-  toErrorCode() => new HintCode(name, message);
-
-  static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke';
-
-  /// Whether this [node] is the target of a dynamic operation.
-  static bool get(AstNode node) {
-    var value = node.getProperty(_propertyName);
-    return value != null ? value : false;
-  }
-
-  /// Sets whether this node is the target of a dynamic operation.
-  static bool set(AstNode node, bool value) {
-    // Free the storage for things that aren't dynamic.
-    if (value == false) value = null;
-    node.setProperty(_propertyName, value);
-    return value;
-  }
-}
-
-abstract class StaticError extends StaticInfo {
-  final AstNode node;
-
-  StaticError(this.node);
-
-  String get message;
-
-  toErrorCode() => new CompileTimeErrorCode(name, message);
-}
-
-class StaticTypeError extends StaticError {
-  final DartType baseType;
-  final DartType expectedType;
-  String reason = null;
-
-  StaticTypeError(TypeRules rules, Expression expression, this.expectedType,
-      {this.reason})
-      : baseType = rules.getStaticType(expression),
-        super(expression);
-
-  @override List<Object> get arguments => [node, baseType, expectedType];
-  @override String get message =>
-      'Type check failed: {0} ({1}) is not of type {2}' +
-          ((reason == null) ? '' : ' because $reason');
-}
-
-class InvalidVariableDeclaration extends StaticError {
-  final DartType expectedType;
-
-  InvalidVariableDeclaration(
-      TypeRules rules, AstNode declaration, this.expectedType)
-      : super(declaration);
-
-  @override List<Object> get arguments => [expectedType];
-  @override String get message => 'Type check failed: null is not of type {0}';
-}
-
-class InvalidParameterDeclaration extends StaticError {
-  final DartType expectedType;
-
-  InvalidParameterDeclaration(
-      TypeRules rules, FormalParameter declaration, this.expectedType)
-      : super(declaration);
-
-  @override List<Object> get arguments => [node, expectedType];
-  @override String get message => 'Type check failed: {0} is not of type {1}';
-}
-
-class NonGroundTypeCheckInfo extends StaticInfo {
-  final DartType type;
-  final AstNode node;
-
-  NonGroundTypeCheckInfo(this.node, this.type) {
-    assert(node is IsExpression || node is AsExpression);
-  }
-
-  @override List<Object> get arguments => [type];
-  String get message =>
-      "Runtime check on non-ground type {0} may throw StrongModeError";
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-// Invalid override of an instance member of a class.
-abstract class InvalidOverride extends StaticError {
-  /// Member declaration with the invalid override.
-  final ExecutableElement element;
-
-  /// Type (class or interface) that provides the base declaration.
-  final InterfaceType base;
-
-  /// Actual type of the overridden member.
-  final DartType subType;
-
-  /// Actual type of the base member.
-  final DartType baseType;
-
-  /// Whether the error comes from combining a base class and an interface
-  final bool fromBaseClass;
-
-  /// Whether the error comes from a mixin (either overriding a base class or an
-  /// interface declaration).
-  final bool fromMixin;
-
-  InvalidOverride(
-      AstNode node, this.element, this.base, this.subType, this.baseType)
-      : fromBaseClass = node is ExtendsClause,
-        fromMixin = node.parent is WithClause,
-        super(node);
-
-  ClassElement get parent => element.enclosingElement;
-
-  @override List<Object> get arguments =>
-      [parent.name, element.name, subType, base, baseType];
-
-  String _messageHelper(String errorName) {
-    var lcErrorName = errorName.toLowerCase();
-    var intro = fromBaseClass
-        ? 'Base class introduces an $lcErrorName'
-        : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName);
-    return '$intro. The type of {0}.{1} ({2}) is not a '
-        'subtype of {3}.{1} ({4}).';
-  }
-}
-
-// Invalid override due to incompatible type.  I.e., the overridden signature
-// is not compatible with the original.
-class InvalidMethodOverride extends InvalidOverride {
-  InvalidMethodOverride(AstNode node, ExecutableElement element,
-      InterfaceType base, FunctionType subType, FunctionType baseType)
-      : super(node, element, base, subType, baseType);
-
-  String get message => _messageHelper('Invalid override');
-}
-
-/// Used to mark unexpected situations in our compiler were we couldn't compute
-/// the type of an expression.
-// TODO(sigmund): This is normally a result of another error that is caught by
-// the analyzer, so this should likely be removed in the future.
-class MissingTypeError extends StaticInfo {
-  final AstNode node;
-  toErrorCode() => new StaticTypeWarningCode(name, message);
-
-  MissingTypeError(this.node);
-
-  @override List<Object> get arguments => [node, node.runtimeType];
-  String get message => "type analysis didn't compute the type of: {0} {1}";
-}
-
-/// Dart constructors have one weird quirk, illustrated with this example:
-///
-///     class Base {
-///       var x;
-///       Base() : x = print('Base.1') {
-///         print('Base.2');
-///       }
-///     }
-///
-///     class Derived extends Base {
-///       var y, z;
-///       Derived()
-///           : y = print('Derived.1'),
-///             super(),
-///             z = print('Derived.2') {
-///         print('Derived.3');
-///       }
-///     }
-///
-/// The order will be Derived.1, Base.1, Derived.2, Base.2, Derived.3; this
-/// ordering preserves the invariant that code can't observe uninitialized
-/// state, however it results in super constructor body not being run
-/// immediately after super initializers. Normally this isn't observable, but it
-/// could be if initializers have side effects.
-///
-/// Better to have `super` at the end, as required by the Dart style guide:
-/// <http://goo.gl/q1T4BB>
-///
-/// For now this is the only pattern we support.
-class InvalidSuperInvocation extends StaticError {
-  InvalidSuperInvocation(SuperConstructorInvocation node) : super(node);
-
-  @override String get message => "super call must be last in an initializer "
-      "list (see http://goo.gl/q1T4BB): {0}";
-}
diff --git a/lib/src/server/server.dart b/lib/src/server/server.dart
index 9a6320f..079b231 100644
--- a/lib/src/server/server.dart
+++ b/lib/src/server/server.dart
@@ -84,7 +84,7 @@
     var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2);
     _log.fine('Compiled ${_libraries.length} libraries in ${time} s\n');
     return new CheckerResults(
-        _libraries, rules, _failure || options.codegenOptions.forceCompile);
+        _libraries, _failure || options.codegenOptions.forceCompile);
   }
 
   bool _buildSource(SourceNode node) {
@@ -154,9 +154,7 @@
     for (var unit in libraryUnit.libraryThenParts) {
       var unitSource = unit.element.source;
       // TODO(sigmund): integrate analyzer errors with static-info (issue #6).
-      failureInLib = logErrors(unitSource) || failureInLib;
-      checker.visitCompilationUnit(unit);
-      if (checker.failure) failureInLib = true;
+      failureInLib = computeErrors(unitSource) || failureInLib;
     }
     if (failureInLib) {
       _failure = true;
@@ -310,4 +308,4 @@
 }
 
 final _log = new Logger('dev_compiler.src.server');
-final _earlyErrorResult = new CheckerResults(const [], null, true);
+final _earlyErrorResult = new CheckerResults(const [], true);
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index b561c59..b38f531 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -380,30 +380,6 @@
 // TODO(vsm): Move this onto the appropriate class.  Ideally, we'd attach
 // it to TypeProvider.
 
-final _objectMap = new Expando('providerToObjectMap');
-Map<String, DartType> getObjectMemberMap(TypeProvider typeProvider) {
-  var map = _objectMap[typeProvider] as Map<String, DartType>;
-  if (map == null) {
-    map = <String, DartType>{};
-    _objectMap[typeProvider] = map;
-    var objectType = typeProvider.objectType;
-    var element = objectType.element;
-    // Only record methods (including getters) with no parameters.  As parameters are contravariant wrt
-    // type, using Object's version may be too strict.
-    // Add instance methods.
-    element.methods.where((method) => !method.isStatic).forEach((method) {
-      map[method.name] = method.type;
-    });
-    // Add getters.
-    element.accessors
-        .where((member) => !member.isStatic && member.isGetter)
-        .forEach((member) {
-      map[member.name] = member.type.returnType;
-    });
-  }
-  return map;
-}
-
 /// Searches all supertype, in order of most derived members, to see if any
 /// [match] a condition. If so, returns the first match, otherwise returns null.
 InterfaceType findSupertype(InterfaceType type, bool match(InterfaceType t)) {
diff --git a/lib/strong_mode.dart b/lib/strong_mode.dart
index 99cef5c..45d17ab 100644
--- a/lib/strong_mode.dart
+++ b/lib/strong_mode.dart
@@ -31,6 +31,7 @@
 
 /// A type checker for Dart code that operates under stronger rules, and has
 /// the ability to do local type inference in some situations.
+// TODO(jmesserly): remove this class.
 class StrongChecker {
   final AnalysisContext _context;
   final CodeChecker _checker;
@@ -41,25 +42,28 @@
   factory StrongChecker(AnalysisContext context, StrongModeOptions options) {
     // TODO(vsm): Remove this once analyzer_cli is completely switched to the
     // task model.
-    if (!AnalysisEngine
-        .instance.useTaskModel) enableDevCompilerInference(context, options);
-    var rules = new TypeRules(context.typeProvider, options: options);
-    var reporter = new _ErrorCollector(options.hints);
-    var checker = new CodeChecker(rules, reporter);
-    return new StrongChecker._(context, checker, reporter);
+    if (!AnalysisEngine.instance.useTaskModel) {
+      enableDevCompilerInference(context, options);
+      var rules = new TypeRules(context.typeProvider);
+      var reporter = new _ErrorCollector(options.hints);
+      var checker = new CodeChecker(rules, reporter);
+      return new StrongChecker._(context, checker, reporter);
+    }
+    return new StrongChecker._(context, null, null);
   }
 
   /// Computes and returns DDC errors for the [source].
   AnalysisErrorInfo computeErrors(Source source) {
     var errors = new List<AnalysisError>();
-    _reporter.errors = errors;
+    if (_checker != null) {
+      _reporter.errors = errors;
 
-    for (Source librarySource in _context.getLibrariesContaining(source)) {
-      var resolved = _context.resolveCompilationUnit2(source, librarySource);
-      _checker.visitCompilationUnit(resolved);
+      for (Source librarySource in _context.getLibrariesContaining(source)) {
+        var resolved = _context.resolveCompilationUnit2(source, librarySource);
+        _checker.visitCompilationUnit(resolved);
+      }
+      _reporter.errors = null;
     }
-    _reporter.errors = null;
-
     return new AnalysisErrorInfoImpl(errors, _context.getLineInfo(source));
   }
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index 7c9dd37..0f56a4c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -41,3 +41,6 @@
   # Similar to dartdevc, but runs the (single) entry point with iojs (requires
   # a very recent iojs next-nightly version).
   dartdevrun: devrun
+
+dependency_overrides:
+  analyzer: { path: ../dart/sdk/pkg/analyzer }
diff --git a/test/all_tests.dart b/test/all_tests.dart
index bd97444..b7c60ca 100644
--- a/test/all_tests.dart
+++ b/test/all_tests.dart
@@ -7,8 +7,6 @@
 
 import 'package:test/test.dart';
 
-import 'checker/checker_test.dart' as checker_test;
-import 'checker/inferred_type_test.dart' as inferred_type_test;
 import 'checker/self_host_test.dart' as self_host;
 import 'closure/closure_annotation_test.dart' as closure_annotation_test;
 import 'closure/closure_type_test.dart' as closure_type_test;
@@ -19,8 +17,6 @@
 
 void main() {
   group('end-to-end', e2e.main);
-  group('inferred types', inferred_type_test.main);
-  group('checker', checker_test.main);
   group('report', report_test.main);
   group('dependency_graph', dependency_graph_test.main);
   group('codegen', () => codegen_test.main([]));
diff --git a/test/testing.dart b/test/testing.dart
index 6874ed3..faa90be 100644
--- a/test/testing.dart
+++ b/test/testing.dart
@@ -28,17 +28,21 @@
 import 'package:dev_compiler/src/utils.dart';
 
 /// Shared analysis context used for compilation.
-final realSdkContext = createAnalysisContextWithSources(
-    new StrongModeOptions(),
-    new SourceResolverOptions(
-        dartSdkPath: getSdkDir().path,
-        customUrlMappings: {
-          'package:expect/expect.dart': _testCodegenPath('expect.dart'),
-          'package:async_helper/async_helper.dart':
-              _testCodegenPath('async_helper.dart'),
-          'package:unittest/unittest.dart': _testCodegenPath('unittest.dart'),
-          'package:dom/dom.dart': _testCodegenPath('sunflower', 'dom.dart')
-        }))..analysisOptions.cacheSize = 512;
+final AnalysisContext realSdkContext = () {
+  var context = createAnalysisContextWithSources(
+      new StrongModeOptions(),
+      new SourceResolverOptions(
+          dartSdkPath: getSdkDir().path,
+          customUrlMappings: {
+            'package:expect/expect.dart': _testCodegenPath('expect.dart'),
+            'package:async_helper/async_helper.dart':
+                _testCodegenPath('async_helper.dart'),
+            'package:unittest/unittest.dart': _testCodegenPath('unittest.dart'),
+            'package:dom/dom.dart': _testCodegenPath('sunflower', 'dom.dart')
+          }));
+  (context.analysisOptions as AnalysisOptionsImpl).cacheSize = 512;
+  return context;
+}();
 
 String _testCodegenPath(String p1, [String p2]) =>
     path.join(testDirectory, 'codegen', p1, p2);
