Disallow implicit casts

Explicit casts make it easier to confidently navigate the code base and
apply refactorings which tighten types. This change exposes a number of
places where types can be tightened, but only the most trivial were
applied. For most places I added the explicit cast that would have
happened anyway and so behavior shouldn't be changing.

- Add the configuration which disallows implicit casts in the analyzer.
- Add explicit casts in almost all instances.
- Where the implicit cast was due to a local variable type on the left,
  change it to a `var` so the type is not repeated.
- In a few places add argument types where they were already applied on
  the parent type, and the subclass was unnecessarily loosening argument
  types to dynamic.
- In a few places where a method was defined with an implicit dynamic
  return but had an obvious and consistent return type, annotate the
  method instead of casting after calls to that method.

Change-Id: I90e11b1cc08ce69967ea5705b507d5758a8f668f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103381
Reviewed-by: Nicholas Shahan <nshahan@google.com>
diff --git a/pkg/dev_compiler/analysis_options.yaml b/pkg/dev_compiler/analysis_options.yaml
index 43cfad3..a4eb32f 100644
--- a/pkg/dev_compiler/analysis_options.yaml
+++ b/pkg/dev_compiler/analysis_options.yaml
@@ -1,4 +1,6 @@
 analyzer:
+  strong-mode:
+    implicit-casts: false
   errors:
     todo: ignore
   exclude:
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index f97e1c2..33fff86 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -610,7 +610,7 @@
 
   @override
   visitExportDirective(ExportDirective node) {
-    ExportElement element = node.element;
+    var element = node.element as ExportElement;
     var currentLibrary = element.library;
 
     var currentNames = currentLibrary.publicNamespace.definedNames;
@@ -2275,7 +2275,7 @@
   JS.Block _emitConstructorBody(ConstructorDeclaration node,
       List<VariableDeclaration> fields, JS.Expression className) {
     var body = <JS.Statement>[];
-    ClassDeclaration cls = node.parent;
+    var cls = node.parent as ClassDeclaration;
 
     // Generate optional/named argument value assignment. These can not have
     // side effects, and may be used by the constructor's initializers, so it's
@@ -2574,7 +2574,7 @@
     }
 
     if (node.isGetter || node.isSetter) {
-      PropertyAccessorElement element = node.declaredElement;
+      var element = node.declaredElement as PropertyAccessorElement;
       var pairAccessor = node.isGetter
           ? element.correspondingSetter
           : element.correspondingGetter;
@@ -2718,7 +2718,7 @@
 
     // Simplify `=> { return e; }` to `=> e`
     if (body is JS.Block) {
-      JS.Block block = body;
+      var block = body as JS.Block;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
         if (s is JS.Return && s.value != null) body = s.value;
@@ -5843,8 +5843,7 @@
     /// fucntion, call it, and yield the result of [yieldType].
     /// TODO(nshahan) Move to share between compilers. Need to work out a common
     /// emitLibraryName().
-    JS.Expression detectYieldAndCall(
-        JS.Statement body, InterfaceType yieldType) {
+    JS.Expression detectYieldAndCall(JS.Block body, InterfaceType yieldType) {
       var finder = YieldFinder();
       body.accept(finder);
       if (finder.hasYield) {
@@ -5871,7 +5870,7 @@
         // a function call that returns the list.
         var functionBody = JS.Block([
           items,
-          node.accept<JS.Node>(this),
+          node.accept<JS.Node>(this) as JS.Statement,
           JS.Return(_currentCollectionVariable)
         ]);
         var functionCall = detectYieldAndCall(functionBody, arrayType);
@@ -5902,7 +5901,7 @@
       ]);
     }
 
-    return pushToCurrentCollection(node);
+    return pushToCurrentCollection(node as Expression);
   }
 
   /// Returns `true` if [node] is a UI-as-Code [CollectionElement].
@@ -6293,7 +6292,7 @@
   JS.Expression _throwUnsafe(String message) => runtimeCall(
       'throw(Error(#))', js.escapedString("compile error: $message"));
 
-  JS.Node _unreachable(Object node) {
+  Null _unreachable(Object node) {
     throw UnsupportedError('tried to generate an unreachable node: `$node`');
   }
 
@@ -6489,7 +6488,7 @@
   @override
   JS.Statement visitForElement(ForElement node) {
     var jsBody = _isUiAsCodeElement(node.body)
-        ? node.body.accept(this)
+        ? node.body.accept(this) as JS.Statement
         : _visitNestedCollectionElement(node.body);
     return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
   }
@@ -6497,13 +6496,13 @@
   @override
   JS.Statement visitIfElement(IfElement node) {
     var thenElement = _isUiAsCodeElement(node.thenElement)
-        ? node.thenElement.accept(this)
+        ? node.thenElement.accept(this) as JS.Statement
         : _visitNestedCollectionElement(node.thenElement);
 
     JS.Statement elseElement;
     if (node.elseElement != null) {
       if (_isUiAsCodeElement(node.elseElement)) {
-        elseElement = node.elseElement.accept<JS.Node>(this);
+        elseElement = node.elseElement.accept<JS.Node>(this) as JS.Statement;
       } else {
         elseElement = _visitNestedCollectionElement(node.elseElement);
       }
@@ -6583,7 +6582,8 @@
     /// Returns [expression] wrapped in an implict cast to [castType] or
     /// [expression] as provided if [castType] is `null` signifying that
     /// no cast is needed.
-    JS.Expression wrapInImplicitCast(JS.Expression expression, castType) =>
+    JS.Expression wrapInImplicitCast(
+            JS.Expression expression, DartType castType) =>
         castType == null ? expression : _emitCast(castType, expression);
 
     /// Returns a statement spreading the elements of [expression] into
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index 8d55999..9e9cb02 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -81,10 +81,10 @@
     var resourceProvider = options.resourceProvider;
     var contextBuilder = options.createContextBuilder();
 
-    var analysisOptions =
-        contextBuilder.getAnalysisOptions(options.analysisRoot);
+    var analysisOptions = contextBuilder
+        .getAnalysisOptions(options.analysisRoot) as AnalysisOptionsImpl;
 
-    (analysisOptions as AnalysisOptionsImpl).enabledExperiments =
+    analysisOptions.enabledExperiments =
         experiments.entries.where((e) => e.value).map((e) => e.key).toList();
 
     var dartSdk = contextBuilder.findSdk(null, analysisOptions);
@@ -336,7 +336,7 @@
 
     var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
     var analyzer = LibraryAnalyzer(
-        analysisOptions,
+        analysisOptions as AnalysisOptionsImpl,
         declaredVariables,
         resynthesizer.sourceFactory,
         (uri) => _isLibraryUri('$uri'),
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 45f443f..e8fe0f0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -124,7 +124,7 @@
   if (node == null) return false;
   var parent = node.parent;
   while (parent is ParenthesizedExpression) {
-    node = parent;
+    node = parent as Expression;
     parent = node.parent;
   }
   return parent is InvocationExpression && identical(node, parent.function) ||
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index a88c582..c258e08 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -59,8 +59,7 @@
     var block = toStatement();
     var s = block.statements;
     if (s.length == 1 && s.first is ExpressionStatement) {
-      ExpressionStatement es = s.first;
-      return es.expression;
+      return (s.first as ExpressionStatement).expression;
     }
 
     return _toInvokedFunction(block);
@@ -114,8 +113,7 @@
     var block = toReturn();
     var s = block.statements;
     if (s.length == 1 && s.first is Return) {
-      Return es = s.first;
-      return _expression = es.value;
+      return (s.first as Return).value;
     }
     // Wrap it in an immediately called function to get in expression context.
     return _expression = _toInvokedFunction(block);
@@ -280,7 +278,7 @@
       }
 
       assert(body.isNotEmpty);
-      Binary newBody = Expression.binary([assign]..addAll(body), ',');
+      var newBody = Expression.binary([assign]..addAll(body), ',') as Binary;
       newBody = _substitute(newBody, {result: left});
       return MetaLet(vars, newBody.commaToExpressionList(),
           statelessResult: statelessResult);
diff --git a/pkg/dev_compiler/lib/src/compiler/js_names.dart b/pkg/dev_compiler/lib/src/compiler/js_names.dart
index a5afca2..24d3dbd 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_names.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_names.dart
@@ -207,7 +207,7 @@
       if (node is FunctionExpression) {
         super.visitFunctionExpression(node);
       } else {
-        super.visitClassExpression(node);
+        super.visitClassExpression(node as ClassExpression);
       }
       _finishScopes();
       scope = scope.parent;
diff --git a/pkg/dev_compiler/lib/src/compiler/js_utils.dart b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
index 74820eb..997702f 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_utils.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
@@ -10,7 +10,7 @@
   if (fn.body is Block && fn.body.statements.length == 1) {
     var stat = fn.body.statements.single;
     if (stat is Return && stat.value is Call) {
-      Call call = stat.value;
+      var call = stat.value as Call;
       var innerFun = call.target;
       if (innerFun is ArrowFun &&
           call.arguments.isEmpty &&
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 05cc667..619ed90 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -142,7 +142,7 @@
     if (name == '[]=') {
       _operatorSetResultStack.add(isLastParamMutated()
           ? JS.TemporaryId((formals.last as JS.Identifier).name)
-          : formals.last);
+          : formals.last as JS.Identifier);
     } else {
       _operatorSetResultStack.add(null);
     }
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index b876e7c..6363cd6 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -361,7 +361,7 @@
 
   @override
   Instantiator<Statement> visitExpressionStatement(ExpressionStatement node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => makeExpression(a).toStatement();
   }
 
@@ -385,8 +385,8 @@
 
   Instantiator<Statement> visitIfConditionalCompilation(
       If node, InterpolatedExpression condition) {
-    Instantiator<Statement> makeThen = visit(node.then);
-    Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+    var makeThen = visit(node.then) as Instantiator<Statement>;
+    var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
     return (arguments) {
       // Allow bools to be used for conditional compliation.
       var nameOrPosition = condition.nameOrPosition;
@@ -400,49 +400,50 @@
   }
 
   Instantiator<Statement> visitIfNormal(If node) {
-    Instantiator<Expression> makeCondition = visit(node.condition);
-    Instantiator<Statement> makeThen = visit(node.then);
-    Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
+    var makeThen = visit(node.then) as Instantiator<Statement>;
+    var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
     return (a) => If(makeCondition(a), makeThen(a), makeOtherwise(a));
   }
 
   @override
   Instantiator<Statement> visitFor(For node) {
-    Instantiator<Expression> makeInit = visitNullable(node.init);
-    Instantiator<Expression> makeCondition = visitNullable(node.condition);
-    Instantiator<Expression> makeUpdate = visitNullable(node.update);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeInit = visitNullable(node.init) as Instantiator<Expression>;
+    var makeCondition =
+        visitNullable(node.condition) as Instantiator<Expression>;
+    var makeUpdate = visitNullable(node.update) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => For(makeInit(a), makeCondition(a),
         makeUpdate(a)?.toVoidExpression(), makeBody(a));
   }
 
   @override
   Instantiator<ForIn> visitForIn(ForIn node) {
-    Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
-    Instantiator<Expression> makeObject = visit(node.object);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+    var makeObject = visit(node.object) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => ForIn(makeLeftHandSide(a), makeObject(a), makeBody(a));
   }
 
   @override
   Instantiator<ForOf> visitForOf(ForOf node) {
-    Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
-    Instantiator<Expression> makeObject = visit(node.iterable);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+    var makeObject = visit(node.iterable) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => ForOf(makeLeftHandSide(a), makeObject(a), makeBody(a));
   }
 
   @override
   Instantiator<While> visitWhile(While node) {
-    Instantiator<Expression> makeCondition = visit(node.condition);
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => While(makeCondition(a), makeBody(a));
   }
 
   @override
   Instantiator<Do> visitDo(Do node) {
-    Instantiator<Statement> makeBody = visit(node.body);
-    Instantiator<Expression> makeCondition = visit(node.condition);
+    var makeBody = visit(node.body) as Instantiator<Statement>;
+    var makeCondition = visit(node.condition) as Instantiator<Expression>;
     return (a) => Do(makeBody(a), makeCondition(a));
   }
 
@@ -456,48 +457,49 @@
   @override
   Instantiator<Statement> visitReturn(Return node) {
     if (node.value == null) return (args) => Return();
-    Instantiator<Expression> makeExpression = visit(node.value);
+    var makeExpression = visit(node.value) as Instantiator<Expression>;
     return (a) => makeExpression(a).toReturn();
   }
 
   @override
   Instantiator<DartYield> visitDartYield(DartYield node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => DartYield(makeExpression(a), node.hasStar);
   }
 
   @override
   Instantiator<Throw> visitThrow(Throw node) {
-    Instantiator<Expression> makeExpression = visit(node.expression);
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     return (a) => Throw(makeExpression(a));
   }
 
   @override
   Instantiator<Try> visitTry(Try node) {
-    Instantiator<Block> makeBody = visit(node.body);
-    Instantiator<Catch> makeCatch = visitNullable(node.catchPart);
-    Instantiator<Block> makeFinally = visitNullable(node.finallyPart);
+    var makeBody = visit(node.body) as Instantiator<Block>;
+    var makeCatch = visitNullable(node.catchPart) as Instantiator<Catch>;
+    var makeFinally = visitNullable(node.finallyPart) as Instantiator<Block>;
     return (a) => Try(makeBody(a), makeCatch(a), makeFinally(a));
   }
 
   @override
   Instantiator<Catch> visitCatch(Catch node) {
-    Instantiator<Identifier> makeDeclaration = visit(node.declaration);
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeDeclaration = visit(node.declaration) as Instantiator<Identifier>;
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (a) => Catch(makeDeclaration(a), makeBody(a));
   }
 
   @override
   Instantiator<Switch> visitSwitch(Switch node) {
-    Instantiator<Expression> makeKey = visit(node.key);
+    var makeKey = visit(node.key) as Instantiator<Expression>;
     var makeCases = node.cases.map(visitSwitchCase).toList();
     return (a) => Switch(makeKey(a), makeCases.map((m) => m(a)).toList());
   }
 
   @override
   Instantiator<SwitchCase> visitSwitchCase(SwitchCase node) {
-    Instantiator<Expression> makeExpression = visitNullable(node.expression);
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeExpression =
+        visitNullable(node.expression) as Instantiator<Expression>;
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (arguments) {
       return SwitchCase(makeExpression(arguments), makeBody(arguments));
     };
@@ -506,14 +508,14 @@
   @override
   Instantiator<FunctionDeclaration> visitFunctionDeclaration(
       FunctionDeclaration node) {
-    Instantiator<Identifier> makeName = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeName = visit(node.name) as Instantiator<Identifier>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => FunctionDeclaration(makeName(a), makeFunction(a));
   }
 
   @override
   Instantiator<LabeledStatement> visitLabeledStatement(LabeledStatement node) {
-    Instantiator<Statement> makeBody = visit(node.body);
+    var makeBody = visit(node.body) as Instantiator<Statement>;
     return (a) => LabeledStatement(node.label, makeBody(a));
   }
 
@@ -539,23 +541,24 @@
     Instantiator makeValue = visitNullable(node.value);
     return (arguments) {
       return makeValue(arguments)
-          .toAssignExpression(makeLeftHandSide(arguments), op);
+          .toAssignExpression(makeLeftHandSide(arguments), op) as Expression;
     };
   }
 
   @override
   Instantiator<VariableInitialization> visitVariableInitialization(
       VariableInitialization node) {
-    Instantiator<VariableBinding> makeDeclaration = visit(node.declaration);
-    Instantiator<Expression> makeValue = visitNullable(node.value);
+    var makeDeclaration =
+        visit(node.declaration) as Instantiator<VariableBinding>;
+    var makeValue = visitNullable(node.value) as Instantiator<Expression>;
     return (a) => VariableInitialization(makeDeclaration(a), makeValue(a));
   }
 
   @override
   Instantiator<Conditional> visitConditional(Conditional cond) {
-    Instantiator<Expression> makeCondition = visit(cond.condition);
-    Instantiator<Expression> makeThen = visit(cond.then);
-    Instantiator<Expression> makeOtherwise = visit(cond.otherwise);
+    var makeCondition = visit(cond.condition) as Instantiator<Expression>;
+    var makeThen = visit(cond.then) as Instantiator<Expression>;
+    var makeOtherwise = visit(cond.otherwise) as Instantiator<Expression>;
     return (a) => Conditional(makeCondition(a), makeThen(a), makeOtherwise(a));
   }
 
@@ -566,7 +569,7 @@
   Instantiator<Call> visitCall(Call node) => handleCallOrNew(node, false);
 
   Instantiator<Call> handleCallOrNew(Call node, bool isNew) {
-    Instantiator<Expression> makeTarget = visit(node.target);
+    var makeTarget = visit(node.target) as Instantiator<Expression>;
     var argumentMakers = node.arguments.map(visitSplayableExpression).toList();
 
     // TODO(sra): Avoid copying call arguments if no interpolation or forced
@@ -580,22 +583,22 @@
 
   @override
   Instantiator<Binary> visitBinary(Binary node) {
-    Instantiator<Expression> makeLeft = visit(node.left);
-    Instantiator<Expression> makeRight = visit(node.right);
+    var makeLeft = visit(node.left) as Instantiator<Expression>;
+    var makeRight = visit(node.right) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Binary(op, makeLeft(a), makeRight(a));
   }
 
   @override
   Instantiator<Prefix> visitPrefix(Prefix node) {
-    Instantiator<Expression> makeOperand = visit(node.argument);
+    var makeOperand = visit(node.argument) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Prefix(op, makeOperand(a));
   }
 
   @override
   Instantiator<Postfix> visitPostfix(Postfix node) {
-    Instantiator<Expression> makeOperand = visit(node.argument);
+    var makeOperand = visit(node.argument) as Instantiator<Expression>;
     String op = node.op;
     return (a) => Postfix(op, makeOperand(a));
   }
@@ -629,22 +632,22 @@
 
   @override
   Instantiator<PropertyAccess> visitAccess(PropertyAccess node) {
-    Instantiator<Expression> makeReceiver = visit(node.receiver);
-    Instantiator<Expression> makeSelector = visit(node.selector);
+    var makeReceiver = visit(node.receiver) as Instantiator<Expression>;
+    var makeSelector = visit(node.selector) as Instantiator<Expression>;
     return (a) => PropertyAccess(makeReceiver(a), makeSelector(a));
   }
 
   @override
   Instantiator<NamedFunction> visitNamedFunction(NamedFunction node) {
-    Instantiator<Identifier> makeDeclaration = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeDeclaration = visit(node.name) as Instantiator<Identifier>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => NamedFunction(makeDeclaration(a), makeFunction(a));
   }
 
   @override
   Instantiator<Fun> visitFun(Fun node) {
     var paramMakers = node.params.map(visitSplayable).toList();
-    Instantiator<Block> makeBody = visit(node.body);
+    var makeBody = visit(node.body) as Instantiator<Block>;
     return (a) => Fun(splayNodes(paramMakers, a), makeBody(a),
         isGenerator: node.isGenerator, asyncModifier: node.asyncModifier);
   }
@@ -653,7 +656,7 @@
   Instantiator<ArrowFun> visitArrowFun(ArrowFun node) {
     var paramMakers = node.params.map(visitSplayable).toList();
     Instantiator makeBody = visit(node.body);
-    return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a));
+    return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a) as Node);
   }
 
   @override
@@ -692,8 +695,8 @@
 
   @override
   Instantiator<Property> visitProperty(Property node) {
-    Instantiator<Expression> makeName = visit(node.name);
-    Instantiator<Expression> makeValue = visit(node.value);
+    var makeName = visit(node.name) as Instantiator<Expression>;
+    var makeValue = visit(node.value) as Instantiator<Expression>;
     return (a) => Property(makeName(a), makeValue(a));
   }
 
@@ -709,7 +712,7 @@
 
   @override
   Instantiator<TaggedTemplate> visitTaggedTemplate(TaggedTemplate node) {
-    Instantiator<Expression> makeTag = visit(node.tag);
+    var makeTag = visit(node.tag) as Instantiator<Expression>;
     var makeTemplate = visitTemplateString(node.template);
     return (a) => TaggedTemplate(makeTag(a), makeTemplate(a));
   }
@@ -723,8 +726,8 @@
   @override
   Instantiator<ClassExpression> visitClassExpression(ClassExpression node) {
     var makeMethods = node.methods.map(visitSplayableExpression).toList();
-    Instantiator<Identifier> makeName = visit(node.name);
-    Instantiator<Expression> makeHeritage = visit(node.heritage);
+    var makeName = visit(node.name) as Instantiator<Identifier>;
+    var makeHeritage = visit(node.heritage) as Instantiator<Expression>;
 
     return (a) => ClassExpression(
         makeName(a), makeHeritage(a), splayNodes(makeMethods, a));
@@ -732,8 +735,8 @@
 
   @override
   Instantiator<Method> visitMethod(Method node) {
-    Instantiator<Expression> makeName = visit(node.name);
-    Instantiator<Fun> makeFunction = visit(node.function);
+    var makeName = visit(node.name) as Instantiator<Expression>;
+    var makeFunction = visit(node.function) as Instantiator<Fun>;
     return (a) => Method(makeName(a), makeFunction(a),
         isGetter: node.isGetter,
         isSetter: node.isSetter,
@@ -747,13 +750,13 @@
   @override
   Instantiator<CommentExpression> visitCommentExpression(
       CommentExpression node) {
-    Instantiator<Expression> makeExpr = visit(node.expression);
+    var makeExpr = visit(node.expression) as Instantiator<Expression>;
     return (a) => CommentExpression(node.comment, makeExpr(a));
   }
 
   @override
   Instantiator<Await> visitAwait(Await node) {
-    Instantiator<Expression> makeExpr = visit(node.expression);
+    var makeExpr = visit(node.expression) as Instantiator<Expression>;
     return (a) => Await(makeExpr(a));
   }
 
@@ -779,11 +782,12 @@
   @override
   Instantiator<DestructuredVariable> visitDestructuredVariable(
       DestructuredVariable node) {
-    Instantiator<Identifier> makeName = visitNullable(node.name);
-    Instantiator<Expression> makeProperty = visitNullable(node.property);
-    Instantiator<BindingPattern> makeStructure = visitNullable(node.structure);
-    Instantiator<Expression> makeDefaultValue =
-        visitNullable(node.defaultValue);
+    var makeName = visitNullable(node.name) as Instantiator<Identifier>;
+    var makeProperty = visitNullable(node.property) as Instantiator<Expression>;
+    var makeStructure =
+        visitNullable(node.structure) as Instantiator<BindingPattern>;
+    var makeDefaultValue =
+        visitNullable(node.defaultValue) as Instantiator<Expression>;
     return (a) => DestructuredVariable(
         name: makeName(a),
         property: makeProperty(a),
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 308e199..caa8b83 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -645,7 +645,9 @@
     var f = type as a.FunctionType;
     if (f.name != null && f.name != '') {
       var ref = ensureNode
-          ? visitFunctionTypeAliasElement(f.element).reference
+          ? visitFunctionTypeAliasElement(
+                  f.element as a.FunctionTypeAliasElement)
+              .reference
           : _reference(f.element);
       return TypedefType.byReference(ref, f.typeArguments.map(visit).toList());
     }
@@ -752,8 +754,8 @@
       void Function(Expression) addAnnotation) {
     if (metadata.isEmpty) return;
 
-    for (a.ElementAnnotationImpl annotation in metadata) {
-      var ast = annotation.annotationAst;
+    for (a.ElementAnnotation annotation in metadata) {
+      var ast = (annotation as a.ElementAnnotationImpl).annotationAst;
       var arguments = ast.arguments;
       if (arguments == null) {
         var e = ast.element;
@@ -833,7 +835,8 @@
         //
         // This leads to mismatch in how we call this constructor. So we need to
         // find the redirected one.
-        for (var rc; (rc = constructor.redirectedConstructor) != null;) {
+        for (a.ConstructorElement rc;
+            (rc = constructor.redirectedConstructor) != null;) {
           constructor = rc;
         }
         constructor = constructor is a.ConstructorMember
@@ -852,7 +855,9 @@
     }
     if (obj is a.DartObjectImpl && type is a.FunctionType) {
       var e = obj.toFunctionValue();
-      e = e is a.PropertyAccessorElement && e.isSynthetic ? e.variable : e;
+      e = e is a.PropertyAccessorElement && e.isSynthetic
+          ? e.variable as a.ExecutableElement
+          : e;
       // TODO(jmesserly): support generic tear-off implicit instantiation.
       return StaticGet.byReference(_reference(e));
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 8794109..7507c3a 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -11,6 +11,7 @@
 import 'package:cli_util/cli_util.dart' show getSdkPath;
 import 'package:front_end/src/api_unstable/ddc.dart' as fe;
 import 'package:kernel/kernel.dart' hide MapEntry;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
 import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
@@ -265,7 +266,7 @@
     converter.dispose();
   }
 
-  var hierarchy;
+  ClassHierarchy hierarchy;
   fe.DdcResult result;
   if (useAnalyzer || !useIncrementalCompiler) {
     result = await fe.compile(compilerState, inputs, diagnosticMessageHandler);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 7427bbc..3dc3e06 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1164,7 +1164,7 @@
     var savedClass = _classEmittingSignatures;
     _classEmittingSignatures = c;
 
-    var interfaces = List.from(c.implementedTypes)
+    var interfaces = c.implementedTypes.toList()
       ..addAll(c.superclassConstraints());
     if (interfaces.isNotEmpty) {
       body.add(js.statement('#[#.implements] = () => [#];', [
@@ -2672,7 +2672,8 @@
   }
 
   @override
-  visitTypedefType(type) => visitFunctionType(type.unalias);
+  visitTypedefType(TypedefType type) =>
+      visitFunctionType(type.unalias as FunctionType);
 
   JS.Fun _emitFunction(FunctionNode f, String name) {
     // normal function (sync), vs (sync*, async, async*)
@@ -2698,11 +2699,11 @@
 
   List<JS.Parameter> _emitParameters(FunctionNode f) {
     var positional = f.positionalParameters;
-    var result = List<JS.Parameter>.from(positional.map(_emitVariableDef));
+    var result = List<JS.Parameter>.of(positional.map(_emitVariableDef));
     if (positional.isNotEmpty &&
         f.requiredParameterCount == positional.length &&
         positional.last.annotations.any(isJsRestAnnotation)) {
-      result.last = JS.RestParameter(result.last);
+      result.last = JS.RestParameter(result.last as JS.Identifier);
     }
     if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
     return result;
@@ -3724,7 +3725,7 @@
 
   @override
   visitConstantExpression(ConstantExpression node) =>
-      node.constant.accept(this);
+      node.constant.accept(this) as JS.Expression;
 
   @override
   visitVariableGet(VariableGet node) {
@@ -4006,7 +4007,7 @@
     return null;
   }
 
-  _isDynamicOrFunction(DartType t) =>
+  bool _isDynamicOrFunction(DartType t) =>
       t == coreTypes.functionClass.rawType || t == const DynamicType();
 
   JS.Expression _emitUnaryOperator(
@@ -4672,7 +4673,9 @@
 
     if (isFromEnvironmentInvocation(coreTypes, node)) {
       var value = _constants.evaluate(node);
-      if (value is PrimitiveConstant) return value.accept(this);
+      if (value is PrimitiveConstant) {
+        return value.accept(this) as JS.Expression;
+      }
     }
 
     if (args.positional.isEmpty &&
@@ -4953,7 +4956,7 @@
   @override
   visitTypeLiteral(TypeLiteral node) => _emitTypeLiteral(node.type);
 
-  _emitTypeLiteral(DartType type) {
+  JS.Expression _emitTypeLiteral(DartType type) {
     var typeRep = _emitType(type);
     // If the type is a type literal expression in Dart code, wrap the raw
     // runtime type in a "Type" instance.
@@ -5069,11 +5072,11 @@
 
     // Simplify `=> { return e; }` to `=> e`
     if (body is JS.Block) {
-      JS.Block block = body;
+      var block = body as JS.Block;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
         if (s is JS.Block) {
-          block = s;
+          block = s as JS.Block;
           s = block.statements.length == 1 ? block.statements[0] : null;
         }
         if (s is JS.Return && s.value != null) body = s.value;
@@ -5204,10 +5207,11 @@
   /// Calls [findAnnotation] followed by [getNameFromAnnotation].
   String getAnnotationName(NamedNode node, bool test(Expression value)) {
     return _constants.getFieldValueFromAnnotation(
-        findAnnotation(node, test), 'name');
+        findAnnotation(node, test), 'name') as String;
   }
 
-  JS.Expression visitConstant(Constant node) => node.accept(this);
+  JS.Expression visitConstant(Constant node) =>
+      node.accept(this) as JS.Expression;
   @override
   visitNullConstant(NullConstant node) => JS.LiteralNull();
   @override
@@ -5267,7 +5271,7 @@
   @override
   visitInstanceConstant(node) {
     entryToProperty(MapEntry<Reference, Constant> entry) {
-      var constant = entry.value.accept(this);
+      var constant = entry.value.accept(this) as JS.Expression;
       var member = entry.key.asField;
       return JS.Property(
           _emitMemberName(member.name.name, member: member), constant);
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index 4fe583b..7ba5c24 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -118,7 +118,7 @@
   final CoreTypes coreTypes;
   _ConstantVisitor(this.coreTypes);
 
-  bool isConstant(Expression e) => e.accept(this);
+  bool isConstant(Expression e) => e.accept(this) as bool;
 
   @override
   defaultExpression(node) => false;
diff --git a/pkg/dev_compiler/lib/src/kernel/native_types.dart b/pkg/dev_compiler/lib/src/kernel/native_types.dart
index 99a2140..d5450f6 100644
--- a/pkg/dev_compiler/lib/src/kernel/native_types.dart
+++ b/pkg/dev_compiler/lib/src/kernel/native_types.dart
@@ -142,7 +142,7 @@
   /// field (which is also the constructor parameter).
   String _getNativeAnnotationName(Expression annotation) {
     if (!_isNativeAnnotation(annotation)) return null;
-    return constants.getFieldValueFromAnnotation(annotation, 'name');
+    return constants.getFieldValueFromAnnotation(annotation, 'name') as String;
   }
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 185d3f0..481a4e8 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -230,7 +230,7 @@
   @override
   visitConstantExpression(ConstantExpression node) {
     var c = node.constant;
-    if (c is UnevaluatedConstant) return c.expression.accept(this);
+    if (c is UnevaluatedConstant) return c.expression.accept(this) as bool;
     if (c is PrimitiveConstant) return c.value == null;
     return false;
   }
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index de9c620..4a3ff15 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -70,7 +70,8 @@
     bool succeeded = false;
     try {
       var result = await compile(args, compilerState: context.compilerState);
-      context.compilerState = result.compilerState;
+      context.compilerState =
+          result.compilerState as fe.InitializedCompilerState;
       succeeded = result.success;
     } catch (e, s) {
       print('Unhandled exception:');
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index d5cb090..5b9a979 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -271,7 +271,7 @@
   void _maybePatch(Declaration node) {
     if (node is FieldDeclaration) return;
 
-    Token externalKeyword = (node as dynamic).externalKeyword;
+    var externalKeyword = (node as dynamic).externalKeyword as Token;
     if (externalKeyword == null) return;
 
     var name = _qualifiedName(node);
@@ -361,7 +361,7 @@
     result = "${parent.name.name}.";
   }
 
-  SimpleIdentifier name = (node as dynamic).name;
+  var name = (node as dynamic).name as SimpleIdentifier;
   if (name != null) result += name.name;
 
   // Make sure setters and getters don't collide.